@axis-backstage/plugin-jira-dashboard-backend 6.1.1 → 6.1.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 +14 -0
- package/dist/actions/createGetJiraTicketInfoAction.cjs.js.map +1 -1
- package/dist/api.cjs.js +21 -20
- package/dist/api.cjs.js.map +1 -1
- package/dist/config.cjs.js.map +1 -1
- package/dist/filters.cjs.js.map +1 -1
- package/dist/lib.cjs.js.map +1 -1
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/queries.cjs.js.map +1 -1
- package/dist/service/defaultValues.cjs.js.map +1 -1
- package/dist/service/router.cjs.js +8 -7
- package/dist/service/router.cjs.js.map +1 -1
- package/dist/service/service.cjs.js +23 -26
- package/dist/service/service.cjs.js.map +1 -1
- package/package.json +12 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @axis-backstage/plugin-jira-dashboard-backend
|
|
2
2
|
|
|
3
|
+
## 6.1.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 36858a7: Bumped to backstage 1.50.2
|
|
8
|
+
- Updated dependencies [36858a7]
|
|
9
|
+
- @axis-backstage/plugin-jira-dashboard-common@1.15.1
|
|
10
|
+
|
|
11
|
+
## 6.1.2
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- a1d5a9a: Refactored the Jira Dashboard backend to batch project keys into a single JQL query (getIssuesByFilter) and to run independent async operations concurrently with Promise.all / Promise.allSettled, reducing latency when multiple projects or filters are fetched.
|
|
16
|
+
|
|
3
17
|
## 6.1.1
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createGetJiraTicketInfoAction.cjs.js","sources":["../../src/actions/createGetJiraTicketInfoAction.ts"],"sourcesContent":["import { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha';\nimport {\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { JiraConfig } from '../config';\nimport { getIssueByKey } from '../api';\n\nexport const createGetJiraTicketInfoAction = ({\n actionsRegistry,\n rootConfig,\n logger,\n}: {\n actionsRegistry: ActionsRegistryService;\n rootConfig: RootConfigService;\n logger: LoggerService;\n}) => {\n actionsRegistry.register({\n name: 'get-jira-ticket-info',\n title: 'Get Jira Ticket Information',\n description:\n 'Retrieves summary and description for a Jira ticket by its key. Use this when users ask about a specific issue or need ticket details.',\n schema: {\n input: z =>\n z.object({\n issueKey: z\n .string()\n .describe(\n 'Jira issue key in format PROJECT-NUMBER (e.g., \"PROJ-123\", \"ABC-456\")',\n ),\n instance: z\n .string()\n .optional()\n .describe(\n 'Jira instance name when multiple instances are configured. Omit to use the default instance.',\n ),\n }),\n output: z =>\n z.object({\n key: z.string().describe('The Jira issue key'),\n summary: z\n .string()\n .optional()\n .describe('Brief one-line summary of the issue'),\n description: z\n .string()\n .optional()\n .describe(\n 'Detailed description of the issue. May be empty if no description was provided.',\n ),\n }),\n },\n action: async ({ input }) => {\n const config = JiraConfig.fromConfig(rootConfig);\n const instance = config.getInstance(input.instance);\n\n try {\n const issue = await getIssueByKey(input.issueKey, instance);\n\n return {\n output: {\n key: issue.key,\n summary: issue.fields?.summary,\n description: issue.fields?.description,\n },\n };\n } catch (error) {\n logger.error(`Failed to fetch Jira ticket ${input.issueKey}: ${error}`);\n throw error;\n }\n },\n });\n};\n"],"names":["config","JiraConfig","getIssueByKey"],"mappings":";;;;;AAQO,MAAM,gCAAgC,CAAC;AAAA,EAC5C,eAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,
|
|
1
|
+
{"version":3,"file":"createGetJiraTicketInfoAction.cjs.js","sources":["../../src/actions/createGetJiraTicketInfoAction.ts"],"sourcesContent":["import { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha';\nimport {\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { JiraConfig } from '../config';\nimport { getIssueByKey } from '../api';\n\nexport const createGetJiraTicketInfoAction = ({\n actionsRegistry,\n rootConfig,\n logger,\n}: {\n actionsRegistry: ActionsRegistryService;\n rootConfig: RootConfigService;\n logger: LoggerService;\n}) => {\n actionsRegistry.register({\n name: 'get-jira-ticket-info',\n title: 'Get Jira Ticket Information',\n description:\n 'Retrieves summary and description for a Jira ticket by its key. Use this when users ask about a specific issue or need ticket details.',\n schema: {\n input: z =>\n z.object({\n issueKey: z\n .string()\n .describe(\n 'Jira issue key in format PROJECT-NUMBER (e.g., \"PROJ-123\", \"ABC-456\")',\n ),\n instance: z\n .string()\n .optional()\n .describe(\n 'Jira instance name when multiple instances are configured. Omit to use the default instance.',\n ),\n }),\n output: z =>\n z.object({\n key: z.string().describe('The Jira issue key'),\n summary: z\n .string()\n .optional()\n .describe('Brief one-line summary of the issue'),\n description: z\n .string()\n .optional()\n .describe(\n 'Detailed description of the issue. May be empty if no description was provided.',\n ),\n }),\n },\n action: async ({ input }) => {\n const config = JiraConfig.fromConfig(rootConfig);\n const instance = config.getInstance(input.instance);\n\n try {\n const issue = await getIssueByKey(input.issueKey, instance);\n\n return {\n output: {\n key: issue.key,\n summary: issue.fields?.summary,\n description: issue.fields?.description,\n },\n };\n } catch (error) {\n logger.error(`Failed to fetch Jira ticket ${input.issueKey}: ${error}`);\n throw error;\n }\n },\n });\n};\n"],"names":["config","JiraConfig","getIssueByKey"],"mappings":";;;;;AAQO,MAAM,gCAAgC,CAAC;AAAA,EAC5C,eAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,KAIM;AACJ,EAAA,eAAA,CAAgB,QAAA,CAAS;AAAA,IACvB,IAAA,EAAM,sBAAA;AAAA,IACN,KAAA,EAAO,6BAAA;AAAA,IACP,WAAA,EACE,wIAAA;AAAA,IACF,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO,CAAA,CAAA,KACL,CAAA,CAAE,MAAA,CAAO;AAAA,QACP,QAAA,EAAU,CAAA,CACP,MAAA,EAAO,CACP,QAAA;AAAA,UACC;AAAA,SACF;AAAA,QACF,QAAA,EAAU,CAAA,CACP,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,UACC;AAAA;AACF,OACH,CAAA;AAAA,MACH,MAAA,EAAQ,CAAA,CAAA,KACN,CAAA,CAAE,MAAA,CAAO;AAAA,QACP,GAAA,EAAK,CAAA,CAAE,MAAA,EAAO,CAAE,SAAS,oBAAoB,CAAA;AAAA,QAC7C,SAAS,CAAA,CACN,MAAA,GACA,QAAA,EAAS,CACT,SAAS,qCAAqC,CAAA;AAAA,QACjD,WAAA,EAAa,CAAA,CACV,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,UACC;AAAA;AACF,OACH;AAAA,KACL;AAAA,IACA,MAAA,EAAQ,OAAO,EAAE,KAAA,EAAM,KAAM;AAC3B,MAAA,MAAMA,QAAA,GAASC,iBAAA,CAAW,UAAA,CAAW,UAAU,CAAA;AAC/C,MAAA,MAAM,QAAA,GAAWD,QAAA,CAAO,WAAA,CAAY,KAAA,CAAM,QAAQ,CAAA;AAElD,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,GAAQ,MAAME,iBAAA,CAAc,KAAA,CAAM,UAAU,QAAQ,CAAA;AAE1D,QAAA,OAAO;AAAA,UACL,MAAA,EAAQ;AAAA,YACN,KAAK,KAAA,CAAM,GAAA;AAAA,YACX,OAAA,EAAS,MAAM,MAAA,EAAQ,OAAA;AAAA,YACvB,WAAA,EAAa,MAAM,MAAA,EAAQ;AAAA;AAC7B,SACF;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,MAAA,CAAO,MAAM,CAAA,4BAAA,EAA+B,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK,KAAK,CAAA,CAAE,CAAA;AACtE,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF;AAAA,GACD,CAAA;AACH;;;;"}
|
package/dist/api.cjs.js
CHANGED
|
@@ -63,28 +63,29 @@ const getQueryUrl = (instance, jql) => {
|
|
|
63
63
|
return baseUrlWithEndpoint;
|
|
64
64
|
};
|
|
65
65
|
const getIssuesByFilter = async (projects, components, query) => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (response?.errorMessages) {
|
|
78
|
-
throw Error(
|
|
79
|
-
`JQL returned Error: JQL - ${jql} with error: ${response?.errorMessages?.[0]}`
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
if (response?.issues) {
|
|
83
|
-
lib.replaceIssuesApiUrl(project.instance, response.issues);
|
|
84
|
-
issues.push(...response.issues);
|
|
66
|
+
if (projects.length === 0) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
const { instance } = projects[0];
|
|
70
|
+
const projectKeys = projects.map((p) => p.projectKey);
|
|
71
|
+
const jql = queries.jqlQueryBuilder({ project: projectKeys, components, query });
|
|
72
|
+
const queryUrl = getQueryUrl(instance, jql);
|
|
73
|
+
const response = await callApi(instance, queryUrl, {
|
|
74
|
+
method: "GET",
|
|
75
|
+
headers: {
|
|
76
|
+
Accept: "application/json"
|
|
85
77
|
}
|
|
78
|
+
}).then((resp) => resp.json()).catch(() => null);
|
|
79
|
+
if (response?.errorMessages) {
|
|
80
|
+
throw Error(
|
|
81
|
+
`JQL returned Error: JQL - ${jql} with error: ${response?.errorMessages?.[0]}`
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
if (response?.issues) {
|
|
85
|
+
lib.replaceIssuesApiUrl(instance, response.issues);
|
|
86
|
+
return response.issues;
|
|
86
87
|
}
|
|
87
|
-
return
|
|
88
|
+
return [];
|
|
88
89
|
};
|
|
89
90
|
const searchJira = async (instance, jqlQuery, options) => {
|
|
90
91
|
const queryUrl = getQueryUrl(instance);
|
package/dist/api.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.cjs.js","sources":["../src/api.ts"],"sourcesContent":["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 { getApiUrl, replaceProjectApiUrl, replaceIssuesApiUrl } 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 `${getApiUrl(instance)}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\n const projectResponse = await response.json();\n replaceProjectApiUrl(project.instance, projectResponse);\n return projectResponse;\n};\n\nexport const getFilterById = async (\n id: string,\n instance: ConfigInstance,\n): Promise<Filter> => {\n const response = await callApi(\n instance,\n `${getApiUrl(instance)}filter/${id}`,\n {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\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 getQueryUrl = (instance: ConfigInstance, jql?: string): string => {\n const baseUrl = getApiUrl(instance);\n\n if (instance.useApiV3) {\n const baseUrlWithEndpoint = `${baseUrl}search/jql`;\n if (jql) {\n return `${baseUrlWithEndpoint}?jql=${jql}&fields=*all`;\n }\n return baseUrlWithEndpoint;\n }\n\n const baseUrlWithEndpoint = `${baseUrl}search`;\n if (jql) {\n return `${baseUrlWithEndpoint}?jql=${jql}`;\n }\n return baseUrlWithEndpoint;\n};\n\nexport const getIssuesByFilter = async (\n projects: JiraProject[],\n components: string[],\n query: string,\n): Promise<Issue[]> => {\n const issues: Issue[] = [];\n for (const project of projects) {\n const { projectKey, instance } = project;\n const jql = jqlQueryBuilder({ project: [projectKey], components, query });\n const queryUrl = getQueryUrl(instance, jql);\n const response = await callApi(instance, queryUrl, {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n })\n .then(resp => resp.json())\n .catch(() => null);\n if (response?.errorMessages) {\n throw Error(\n `JQL returned Error: JQL - ${jql} with error: ${response?.errorMessages?.[0]}`,\n );\n }\n if (response?.issues) {\n replaceIssuesApiUrl(project.instance, response.issues);\n issues.push(...response.issues);\n }\n }\n\n return 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 queryUrl = getQueryUrl(instance);\n const requestBody = { jql: jqlQuery, ...options };\n\n const response = await callApi(instance, queryUrl, {\n method: 'POST',\n body: JSON.stringify(requestBody),\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()) as JiraQueryResults;\n replaceIssuesApiUrl(instance, jsonResponse.issues);\n return jsonResponse;\n};\n\nexport const getIssuesByComponent = async (\n projects: JiraProject[],\n componentKeys: string,\n query?: string,\n): Promise<Issue[]> => {\n // Return an empty array if no projects are provided\n if (projects.length === 0) {\n return [];\n }\n\n const projectKeys = projects.map(project => project.projectKey);\n const components = componentKeys\n .split(',')\n .map(component => component.trim());\n\n const jql = jqlQueryBuilder({\n project: projectKeys,\n components,\n query,\n });\n\n const { instance } = projects[0];\n\n try {\n const queryUrl = getQueryUrl(instance, jql);\n const response = await callApi(instance, queryUrl, {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n }).then(resp => resp.json());\n\n if (!response.issues || response.issues.length === 0) {\n return [];\n }\n\n replaceIssuesApiUrl(instance, response.issues);\n return response.issues;\n } catch (error: any) {\n if (error.message.includes(\"does not exist for the field 'project'\")) {\n return [];\n }\n throw error;\n }\n};\nexport async function getProjectAvatar(url: string, instance: ConfigInstance) {\n return callApi(instance, url);\n}\n\n/**\n * Get a single Jira issue by its key or ID.\n *\n * @param issueKey - The issue key (e.g., \"PROJ-123\") or ID\n * @param instance - The Jira instance configuration\n * @returns The Jira issue\n * @public\n */\nexport const getIssueByKey = async (\n issueKey: string,\n instance: ConfigInstance,\n): Promise<Issue> => {\n const response = await callApi(\n instance,\n `${getApiUrl(instance)}issue/${issueKey}?fields=summary,description`,\n {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n },\n );\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const issue = (await response.json()) as Issue;\n return issue;\n};\n\n/**\n * Call the Jira API using fetch.\n *\n * This function injects the auth token and custom headers.\n *\n * @public\n */\nexport async 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"],"names":["getApiUrl","replaceProjectApiUrl","baseUrlWithEndpoint","jqlQueryBuilder","replaceIssuesApiUrl","ResponseError","fetch"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api.cjs.js","sources":["../src/api.ts"],"sourcesContent":["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 { getApiUrl, replaceProjectApiUrl, replaceIssuesApiUrl } 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 `${getApiUrl(instance)}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\n const projectResponse = await response.json();\n replaceProjectApiUrl(project.instance, projectResponse);\n return projectResponse;\n};\n\nexport const getFilterById = async (\n id: string,\n instance: ConfigInstance,\n): Promise<Filter> => {\n const response = await callApi(\n instance,\n `${getApiUrl(instance)}filter/${id}`,\n {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\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 getQueryUrl = (instance: ConfigInstance, jql?: string): string => {\n const baseUrl = getApiUrl(instance);\n\n if (instance.useApiV3) {\n const baseUrlWithEndpoint = `${baseUrl}search/jql`;\n if (jql) {\n return `${baseUrlWithEndpoint}?jql=${jql}&fields=*all`;\n }\n return baseUrlWithEndpoint;\n }\n\n const baseUrlWithEndpoint = `${baseUrl}search`;\n if (jql) {\n return `${baseUrlWithEndpoint}?jql=${jql}`;\n }\n return baseUrlWithEndpoint;\n};\n\nexport const getIssuesByFilter = async (\n projects: JiraProject[],\n components: string[],\n query: string,\n): Promise<Issue[]> => {\n if (projects.length === 0) {\n return [];\n }\n\n // All projects are expected to share the same instance — callers (getJiraProjectsFromKeys)\n // stamp every project with the same ConfigInstance, so a single batched JQL query suffices.\n const { instance } = projects[0];\n const projectKeys = projects.map(p => p.projectKey);\n const jql = jqlQueryBuilder({ project: projectKeys, components, query });\n const queryUrl = getQueryUrl(instance, jql);\n\n const response = await callApi(instance, queryUrl, {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n })\n .then(resp => resp.json())\n .catch(() => null);\n\n if (response?.errorMessages) {\n throw Error(\n `JQL returned Error: JQL - ${jql} with error: ${response?.errorMessages?.[0]}`,\n );\n }\n\n if (response?.issues) {\n replaceIssuesApiUrl(instance, response.issues);\n return response.issues;\n }\n\n return [];\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 queryUrl = getQueryUrl(instance);\n const requestBody = { jql: jqlQuery, ...options };\n\n const response = await callApi(instance, queryUrl, {\n method: 'POST',\n body: JSON.stringify(requestBody),\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()) as JiraQueryResults;\n replaceIssuesApiUrl(instance, jsonResponse.issues);\n return jsonResponse;\n};\n\nexport const getIssuesByComponent = async (\n projects: JiraProject[],\n componentKeys: string,\n query?: string,\n): Promise<Issue[]> => {\n // Return an empty array if no projects are provided\n if (projects.length === 0) {\n return [];\n }\n\n const projectKeys = projects.map(project => project.projectKey);\n const components = componentKeys\n .split(',')\n .map(component => component.trim());\n\n const jql = jqlQueryBuilder({\n project: projectKeys,\n components,\n query,\n });\n\n const { instance } = projects[0];\n\n try {\n const queryUrl = getQueryUrl(instance, jql);\n const response = await callApi(instance, queryUrl, {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n }).then(resp => resp.json());\n\n if (!response.issues || response.issues.length === 0) {\n return [];\n }\n\n replaceIssuesApiUrl(instance, response.issues);\n return response.issues;\n } catch (error: any) {\n if (error.message.includes(\"does not exist for the field 'project'\")) {\n return [];\n }\n throw error;\n }\n};\nexport async function getProjectAvatar(url: string, instance: ConfigInstance) {\n return callApi(instance, url);\n}\n\n/**\n * Get a single Jira issue by its key or ID.\n *\n * @param issueKey - The issue key (e.g., \"PROJ-123\") or ID\n * @param instance - The Jira instance configuration\n * @returns The Jira issue\n * @public\n */\nexport const getIssueByKey = async (\n issueKey: string,\n instance: ConfigInstance,\n): Promise<Issue> => {\n const response = await callApi(\n instance,\n `${getApiUrl(instance)}issue/${issueKey}?fields=summary,description`,\n {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n },\n );\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const issue = (await response.json()) as Issue;\n return issue;\n};\n\n/**\n * Call the Jira API using fetch.\n *\n * This function injects the auth token and custom headers.\n *\n * @public\n */\nexport async 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"],"names":["getApiUrl","replaceProjectApiUrl","baseUrlWithEndpoint","jqlQueryBuilder","replaceIssuesApiUrl","ResponseError","fetch"],"mappings":"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"}
|
package/dist/config.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.cjs.js","sources":["../src/config.ts"],"sourcesContent":["import { ConflictError, ServiceUnavailableError } from '@backstage/errors';\nimport { RootConfigService } from '@backstage/backend-plugin-api';\nimport { readDurationFromConfig } from '@backstage/config';\nimport { durationToMilliseconds } from '@backstage/types';\nimport { Filter } from '@axis-backstage/plugin-jira-dashboard-common';\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 apiUrl?: string;\n userEmailSuffix?: string;\n defaultFilters?: Filter[];\n useApiV3?: boolean;\n cacheTtl: number; // TTL in milliseconds\n};\n\nconst JIRA_CONFIG_BASE_URL = 'baseUrl';\nconst JIRA_CONFIG_API_URL = 'apiUrl';\nconst JIRA_CONFIG_TOKEN = 'token';\nconst JIRA_CONFIG_HEADERS = 'headers';\nconst JIRA_CONFIG_USER_EMAIL_SUFFIX = 'userEmailSuffix';\nconst JIRA_CONFIG_ANNOTATION = 'annotationPrefix';\nconst JIRA_FILTERS = 'defaultFilters';\nconst JIRA_CONFIG_USE_API_V3 = 'useApiV3';\nconst JIRA_CONFIG_CACHE_TTL = 'cacheTtl';\n\n/**\n * Get cache TTL in milliseconds for a Jira instance configuration\n * Defaults to 1 hour (3,600,000 ms) if not specified\n */\nfunction getCacheTtl(instanceConfig: Config): number {\n if (!instanceConfig.has(JIRA_CONFIG_CACHE_TTL)) {\n return 3_600_000;\n }\n\n return durationToMilliseconds(\n readDurationFromConfig(instanceConfig, { key: JIRA_CONFIG_CACHE_TTL }),\n );\n}\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 apiUrl: inst.getOptionalString(JIRA_CONFIG_API_URL),\n userEmailSuffix: inst.getOptionalString(\n JIRA_CONFIG_USER_EMAIL_SUFFIX,\n ),\n defaultFilters: inst\n .getOptionalConfigArray(JIRA_FILTERS)\n ?.map(filterConfig => ({\n name: filterConfig.getString('name'),\n shortName: filterConfig.getString('shortName'),\n query: filterConfig.getString('query'),\n })),\n useApiV3: inst.getOptionalBoolean(JIRA_CONFIG_USE_API_V3) ?? false,\n cacheTtl: getCacheTtl(inst),\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 apiUrl: jira.getOptionalString(JIRA_CONFIG_API_URL),\n userEmailSuffix: jira.getOptionalString(JIRA_CONFIG_USER_EMAIL_SUFFIX),\n defaultFilters: jira\n .getOptionalConfigArray(JIRA_FILTERS)\n ?.map(filterConfig => ({\n name: filterConfig.getString('name'),\n shortName: filterConfig.getString('shortName'),\n query: filterConfig.getString('query'),\n })),\n useApiV3: jira.getOptionalBoolean(JIRA_CONFIG_USE_API_V3) ?? false,\n cacheTtl: getCacheTtl(jira),\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 /**\n * Get the defined default filters for a given instance\n */\n resolveDefaultFilters(instanceName: string): Filter[] | undefined {\n const instance = this.forInstance(instanceName);\n return instance.defaultFilters;\n }\n}\n"],"names":["durationToMilliseconds","readDurationFromConfig","ConflictError","ServiceUnavailableError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.cjs.js","sources":["../src/config.ts"],"sourcesContent":["import { ConflictError, ServiceUnavailableError } from '@backstage/errors';\nimport { RootConfigService } from '@backstage/backend-plugin-api';\nimport { readDurationFromConfig } from '@backstage/config';\nimport { durationToMilliseconds } from '@backstage/types';\nimport { Filter } from '@axis-backstage/plugin-jira-dashboard-common';\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 apiUrl?: string;\n userEmailSuffix?: string;\n defaultFilters?: Filter[];\n useApiV3?: boolean;\n cacheTtl: number; // TTL in milliseconds\n};\n\nconst JIRA_CONFIG_BASE_URL = 'baseUrl';\nconst JIRA_CONFIG_API_URL = 'apiUrl';\nconst JIRA_CONFIG_TOKEN = 'token';\nconst JIRA_CONFIG_HEADERS = 'headers';\nconst JIRA_CONFIG_USER_EMAIL_SUFFIX = 'userEmailSuffix';\nconst JIRA_CONFIG_ANNOTATION = 'annotationPrefix';\nconst JIRA_FILTERS = 'defaultFilters';\nconst JIRA_CONFIG_USE_API_V3 = 'useApiV3';\nconst JIRA_CONFIG_CACHE_TTL = 'cacheTtl';\n\n/**\n * Get cache TTL in milliseconds for a Jira instance configuration\n * Defaults to 1 hour (3,600,000 ms) if not specified\n */\nfunction getCacheTtl(instanceConfig: Config): number {\n if (!instanceConfig.has(JIRA_CONFIG_CACHE_TTL)) {\n return 3_600_000;\n }\n\n return durationToMilliseconds(\n readDurationFromConfig(instanceConfig, { key: JIRA_CONFIG_CACHE_TTL }),\n );\n}\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 apiUrl: inst.getOptionalString(JIRA_CONFIG_API_URL),\n userEmailSuffix: inst.getOptionalString(\n JIRA_CONFIG_USER_EMAIL_SUFFIX,\n ),\n defaultFilters: inst\n .getOptionalConfigArray(JIRA_FILTERS)\n ?.map(filterConfig => ({\n name: filterConfig.getString('name'),\n shortName: filterConfig.getString('shortName'),\n query: filterConfig.getString('query'),\n })),\n useApiV3: inst.getOptionalBoolean(JIRA_CONFIG_USE_API_V3) ?? false,\n cacheTtl: getCacheTtl(inst),\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 apiUrl: jira.getOptionalString(JIRA_CONFIG_API_URL),\n userEmailSuffix: jira.getOptionalString(JIRA_CONFIG_USER_EMAIL_SUFFIX),\n defaultFilters: jira\n .getOptionalConfigArray(JIRA_FILTERS)\n ?.map(filterConfig => ({\n name: filterConfig.getString('name'),\n shortName: filterConfig.getString('shortName'),\n query: filterConfig.getString('query'),\n })),\n useApiV3: jira.getOptionalBoolean(JIRA_CONFIG_USE_API_V3) ?? false,\n cacheTtl: getCacheTtl(jira),\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 /**\n * Get the defined default filters for a given instance\n */\n resolveDefaultFilters(instanceName: string): Filter[] | undefined {\n const instance = this.forInstance(instanceName);\n return instance.defaultFilters;\n }\n}\n"],"names":["durationToMilliseconds","readDurationFromConfig","ConflictError","ServiceUnavailableError"],"mappings":"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"}
|
package/dist/filters.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filters.cjs.js","sources":["../src/filters.ts"],"sourcesContent":["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 const defaultFilters =\n instance.defaultFilters?.map(filter => ({\n name: filter.name,\n query: filter.query,\n shortName: filter.shortName,\n })) || [];\n\n if (!userEntity) return [openFilter, incomingFilter, ...defaultFilters];\n\n const assigneeToMeFilter = getAssignedToMeFilter(userEntity, instance);\n\n return [openFilter, incomingFilter, assigneeToMeFilter, ...defaultFilters];\n};\n"],"names":[],"mappings":";;AAIA,MAAM,
|
|
1
|
+
{"version":3,"file":"filters.cjs.js","sources":["../src/filters.ts"],"sourcesContent":["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 const defaultFilters =\n instance.defaultFilters?.map(filter => ({\n name: filter.name,\n query: filter.query,\n shortName: filter.shortName,\n })) || [];\n\n if (!userEntity) return [openFilter, incomingFilter, ...defaultFilters];\n\n const assigneeToMeFilter = getAssignedToMeFilter(userEntity, instance);\n\n return [openFilter, incomingFilter, assigneeToMeFilter, ...defaultFilters];\n};\n"],"names":[],"mappings":";;AAIA,MAAM,UAAA,GAAqB;AAAA,EACzB,IAAA,EAAM,aAAA;AAAA,EACN,SAAA,EAAW,MAAA;AAAA,EACX,KAAA,EAAO;AACT,CAAA;AAEA,MAAM,iBAAA,GAAoB,CAAC,cAAA,MAAoC;AAAA,EAC7D,IAAA,EAAM,iBAAA;AAAA,EACN,SAAA,EAAW,UAAA;AAAA,EACX,KAAA,EAAO,aAAa,cAAc,CAAA,sBAAA;AACpC,CAAA,CAAA;AASO,MAAM,cAAA,GAAiB,CAC5B,QAAA,EACA,UAAA,KACW;AACX,EAAA,MAAM,oBAAoB,QAAA,CAAS,eAAA;AAEnC,EAAA,OAAO,iBAAA,GACH,CAAA,EAAG,UAAA,CAAW,QAAA,CAAS,IAAI,CAAA,EAAG,iBAAiB,CAAA,CAAA,GAC/C,UAAA,CAAW,IAAA,EAAM,OAAA,EAAS,KAAA,IAAS,WAAW,QAAA,CAAS,IAAA;AAC7D;AAEA,MAAM,qBAAA,GAAwB,CAC5B,UAAA,EACA,QAAA,KACW;AACX,EAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,QAAA,EAAU,UAAU,CAAA;AAEjD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,SAAA,EAAW,IAAA;AAAA,IACX,KAAA,EAAO,eAAe,KAAK,CAAA,mDAAA;AAAA,GAC7B;AACF,CAAA;AAEO,MAAM,wBAAA,GAA2B,CACtC,QAAA,EACA,UAAA,EACA,cAAA,KACa;AACb,EAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,cAAA,IAAkB,KAAK,CAAA;AAEhE,EAAA,MAAM,cAAA,GACJ,QAAA,CAAS,cAAA,EAAgB,GAAA,CAAI,CAAA,MAAA,MAAW;AAAA,IACtC,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,WAAW,MAAA,CAAO;AAAA,GACpB,CAAE,KAAK,EAAC;AAEV,EAAA,IAAI,CAAC,UAAA,EAAY,OAAO,CAAC,UAAA,EAAY,cAAA,EAAgB,GAAG,cAAc,CAAA;AAEtE,EAAA,MAAM,kBAAA,GAAqB,qBAAA,CAAsB,UAAA,EAAY,QAAQ,CAAA;AAErE,EAAA,OAAO,CAAC,UAAA,EAAY,cAAA,EAAgB,kBAAA,EAAoB,GAAG,cAAc,CAAA;AAC3E;;;;;"}
|
package/dist/lib.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.cjs.js","sources":["../src/lib.ts"],"sourcesContent":["import {\n COMPONENTS_NAME,\n PROJECT_KEY_NAME,\n FILTERS_NAME,\n INCOMING_ISSUES_STATUS,\n Project,\n Issue,\n JQL,\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 jqlAnnotation = `${prefix}/${JQL}`;\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 jqlAnnotation,\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\nexport function getApiUrl(instance: ConfigInstance) {\n return instance.apiUrl || instance.baseUrl;\n}\n\nexport function replaceProjectApiUrl(\n instance: ConfigInstance,\n project: Project,\n) {\n if (instance.apiUrl) {\n const apiUrl = instance.apiUrl;\n project.self = project.self.replace(apiUrl, instance.baseUrl);\n }\n}\n\nexport function replaceIssuesApiUrl(instance: ConfigInstance, issues: Issue[]) {\n if (instance.apiUrl) {\n const apiUrl = instance.apiUrl;\n issues.forEach(\n issue => (issue.self = issue.self.replace(apiUrl, instance.baseUrl)),\n );\n }\n}\n"],"names":["PROJECT_KEY_NAME","JQL","COMPONENTS_NAME","FILTERS_NAME","INCOMING_ISSUES_STATUS"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"lib.cjs.js","sources":["../src/lib.ts"],"sourcesContent":["import {\n COMPONENTS_NAME,\n PROJECT_KEY_NAME,\n FILTERS_NAME,\n INCOMING_ISSUES_STATUS,\n Project,\n Issue,\n JQL,\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 jqlAnnotation = `${prefix}/${JQL}`;\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 jqlAnnotation,\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\nexport function getApiUrl(instance: ConfigInstance) {\n return instance.apiUrl || instance.baseUrl;\n}\n\nexport function replaceProjectApiUrl(\n instance: ConfigInstance,\n project: Project,\n) {\n if (instance.apiUrl) {\n const apiUrl = instance.apiUrl;\n project.self = project.self.replace(apiUrl, instance.baseUrl);\n }\n}\n\nexport function replaceIssuesApiUrl(instance: ConfigInstance, issues: Issue[]) {\n if (instance.apiUrl) {\n const apiUrl = instance.apiUrl;\n issues.forEach(\n issue => (issue.self = issue.self.replace(apiUrl, instance.baseUrl)),\n );\n }\n}\n"],"names":["PROJECT_KEY_NAME","JQL","COMPONENTS_NAME","FILTERS_NAME","INCOMING_ISSUES_STATUS"],"mappings":";;;;AAYO,MAAM,cAAA,GAAiB,CAAC,MAAA,KAAuB;AACpD,EAAA,MAAM,SAAS,MAAA,CAAO,gBAAA;AAEtB,EAAA,MAAM,oBAAA,GAAuB,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIA,0CAAgB,CAAA,CAAA;AAC1D,EAAA,MAAM,aAAA,GAAgB,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIC,6BAAG,CAAA,CAAA;AACtC,EAAA,MAAM,oBAAA,GAAuB,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIC,yCAAe,CAAA,CAAA;AACzD,EAAA,MAAM,iBAAA,GAAoB,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIC,sCAAY,CAAA,CAAA;AACnD,EAAA,MAAM,wBAAA,GAA2B,CAAA,EAAG,MAAM,CAAA,CAAA,EAAIC,gDAAsB,CAAA,CAAA;AAGpE,EAAA,MAAM,yBAAA,GAA4B,GAAG,MAAM,CAAA,UAAA,CAAA;AAE3C,EAAA,OAAO;AAAA,IACL,oBAAA;AAAA,IACA,aAAA;AAAA,IACA,oBAAA;AAAA,IACA,iBAAA;AAAA,IACA,wBAAA;AAAA,IACA;AAAA,GACF;AACF;AAYO,SAAS,eAAA,CACd,QACA,cAAA,EACa;AACb,EAAA,MAAM,CAAC,QAAA,EAAU,UAAU,CAAA,GAAI,cAAA,CAAe,MAAM,GAAG,CAAA;AACvD,EAAA,IAAI,CAAC,UAAA,EAAY;AAEf,IAAA,OAAO;AAAA,MACL,QAAA,EAAU,OAAO,WAAA,EAAY;AAAA,MAC7B,cAAA;AAAA,MACA,UAAA,EAAY;AAAA,KACd;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,MAAA,CAAO,WAAA,CAAY,QAAQ,CAAA;AAAA,IACrC,cAAA;AAAA,IACA;AAAA,GACF;AACF;AAEO,SAAS,UAAU,QAAA,EAA0B;AAClD,EAAA,OAAO,QAAA,CAAS,UAAU,QAAA,CAAS,OAAA;AACrC;AAEO,SAAS,oBAAA,CACd,UACA,OAAA,EACA;AACA,EAAA,IAAI,SAAS,MAAA,EAAQ;AACnB,IAAA,MAAM,SAAS,QAAA,CAAS,MAAA;AACxB,IAAA,OAAA,CAAQ,OAAO,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,SAAS,OAAO,CAAA;AAAA,EAC9D;AACF;AAEO,SAAS,mBAAA,CAAoB,UAA0B,MAAA,EAAiB;AAC7E,EAAA,IAAI,SAAS,MAAA,EAAQ;AACnB,IAAA,MAAM,SAAS,QAAA,CAAS,MAAA;AACxB,IAAA,MAAA,CAAO,OAAA;AAAA,MACL,CAAA,KAAA,KAAU,MAAM,IAAA,GAAO,KAAA,CAAM,KAAK,OAAA,CAAQ,MAAA,EAAQ,SAAS,OAAO;AAAA,KACpE;AAAA,EACF;AACF;;;;;;;;"}
|
package/dist/plugin.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha';\nimport { createRouter } from './service/router';\nimport { JiraConfig } from './config';\nimport { createGetJiraTicketInfoAction } from './actions/createGetJiraTicketInfoAction';\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 actionsRegistry: actionsRegistryServiceRef,\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 cache: coreServices.cache,\n },\n async init({\n actionsRegistry,\n auth,\n httpRouter,\n logger,\n rootConfig,\n discovery,\n httpAuth,\n userInfo,\n cache,\n }) {\n httpRouter.use(\n await createRouter({\n auth,\n logger,\n config: JiraConfig.fromConfig(rootConfig),\n discovery,\n httpAuth,\n userInfo,\n cache,\n }),\n );\n httpRouter.addAuthPolicy({\n path: '/health',\n allow: 'unauthenticated',\n });\n createGetJiraTicketInfoAction({\n actionsRegistry,\n rootConfig,\n logger,\n });\n },\n });\n },\n});\n"],"names":["createBackendPlugin","actionsRegistryServiceRef","coreServices","createRouter","JiraConfig","createGetJiraTicketInfoAction"],"mappings":";;;;;;;;AAcO,MAAM,sBAAsBA,
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha';\nimport { createRouter } from './service/router';\nimport { JiraConfig } from './config';\nimport { createGetJiraTicketInfoAction } from './actions/createGetJiraTicketInfoAction';\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 actionsRegistry: actionsRegistryServiceRef,\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 cache: coreServices.cache,\n },\n async init({\n actionsRegistry,\n auth,\n httpRouter,\n logger,\n rootConfig,\n discovery,\n httpAuth,\n userInfo,\n cache,\n }) {\n httpRouter.use(\n await createRouter({\n auth,\n logger,\n config: JiraConfig.fromConfig(rootConfig),\n discovery,\n httpAuth,\n userInfo,\n cache,\n }),\n );\n httpRouter.addAuthPolicy({\n path: '/health',\n allow: 'unauthenticated',\n });\n createGetJiraTicketInfoAction({\n actionsRegistry,\n rootConfig,\n logger,\n });\n },\n });\n },\n});\n"],"names":["createBackendPlugin","actionsRegistryServiceRef","coreServices","createRouter","JiraConfig","createGetJiraTicketInfoAction"],"mappings":";;;;;;;;AAcO,MAAM,sBAAsBA,oCAAA,CAAoB;AAAA,EACrD,QAAA,EAAU,gBAAA;AAAA,EACV,SAAS,GAAA,EAAK;AACZ,IAAA,GAAA,CAAI,YAAA,CAAa;AAAA,MACf,IAAA,EAAM;AAAA,QACJ,eAAA,EAAiBC,+BAAA;AAAA,QACjB,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,QACvB,OAAOA,6BAAA,CAAa;AAAA,OACtB;AAAA,MACA,MAAM,IAAA,CAAK;AAAA,QACT,eAAA;AAAA,QACA,IAAA;AAAA,QACA,UAAA;AAAA,QACA,MAAA;AAAA,QACA,UAAA;AAAA,QACA,SAAA;AAAA,QACA,QAAA;AAAA,QACA,QAAA;AAAA,QACA;AAAA,OACF,EAAG;AACD,QAAA,UAAA,CAAW,GAAA;AAAA,UACT,MAAMC,mBAAA,CAAa;AAAA,YACjB,IAAA;AAAA,YACA,MAAA;AAAA,YACA,MAAA,EAAQC,iBAAA,CAAW,UAAA,CAAW,UAAU,CAAA;AAAA,YACxC,SAAA;AAAA,YACA,QAAA;AAAA,YACA,QAAA;AAAA,YACA;AAAA,WACD;AAAA,SACH;AACA,QAAA,UAAA,CAAW,aAAA,CAAc;AAAA,UACvB,IAAA,EAAM,SAAA;AAAA,UACN,KAAA,EAAO;AAAA,SACR,CAAA;AACD,QAAAC,2DAAA,CAA8B;AAAA,UAC5B,eAAA;AAAA,UACA,UAAA;AAAA,UACA;AAAA,SACD,CAAA;AAAA,MACH;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
|
package/dist/queries.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.cjs.js","sources":["../src/queries.ts"],"sourcesContent":["/**\n * Types for the arguments to the jqlQueryBuilder function.\n *\n * @public\n */\nexport type JqlQueryBuilderArgs = {\n project: string | string[];\n components?: string[];\n query?: string;\n};\n\n/**\n * Creates a partial jql query string using the \"in\" operator to\n * include multiple values for a field.\n *\n * Example:\n * \"affectedVersion in ('3.14', '4.2')\"\n *\n * @param field\n * @param values\n */\nexport const createEscapedIncludeQuery = (field: string, values: string[]) => {\n let query = `${field} in (`;\n for (let index = 0; index < values.length; index++) {\n const value = values[index];\n query += `'${value}'`;\n // Add either the \",\" separator or close the parentheses.\n if (index === values.length - 1) {\n query += ')';\n } else {\n query += ',';\n }\n }\n return query;\n};\n\n/**\n * Builds a JQL (Jira Query Language) query string based on the provided arguments.\n *\n * @public\n */\nexport const jqlQueryBuilder = ({\n project,\n components,\n query,\n}: JqlQueryBuilderArgs) => {\n const projectList = Array.isArray(project) ? project : [project];\n let jql = createEscapedIncludeQuery('project', projectList);\n if (components?.length) {\n jql += ` AND ${createEscapedIncludeQuery('component', components)}`;\n }\n if (query) {\n jql += ` AND ${query}`;\n }\n return jql;\n};\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"queries.cjs.js","sources":["../src/queries.ts"],"sourcesContent":["/**\n * Types for the arguments to the jqlQueryBuilder function.\n *\n * @public\n */\nexport type JqlQueryBuilderArgs = {\n project: string | string[];\n components?: string[];\n query?: string;\n};\n\n/**\n * Creates a partial jql query string using the \"in\" operator to\n * include multiple values for a field.\n *\n * Example:\n * \"affectedVersion in ('3.14', '4.2')\"\n *\n * @param field\n * @param values\n */\nexport const createEscapedIncludeQuery = (field: string, values: string[]) => {\n let query = `${field} in (`;\n for (let index = 0; index < values.length; index++) {\n const value = values[index];\n query += `'${value}'`;\n // Add either the \",\" separator or close the parentheses.\n if (index === values.length - 1) {\n query += ')';\n } else {\n query += ',';\n }\n }\n return query;\n};\n\n/**\n * Builds a JQL (Jira Query Language) query string based on the provided arguments.\n *\n * @public\n */\nexport const jqlQueryBuilder = ({\n project,\n components,\n query,\n}: JqlQueryBuilderArgs) => {\n const projectList = Array.isArray(project) ? project : [project];\n let jql = createEscapedIncludeQuery('project', projectList);\n if (components?.length) {\n jql += ` AND ${createEscapedIncludeQuery('component', components)}`;\n }\n if (query) {\n jql += ` AND ${query}`;\n }\n return jql;\n};\n"],"names":[],"mappings":";;AAqBO,MAAM,yBAAA,GAA4B,CAAC,KAAA,EAAe,MAAA,KAAqB;AAC5E,EAAA,IAAI,KAAA,GAAQ,GAAG,KAAK,CAAA,KAAA,CAAA;AACpB,EAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,MAAA,CAAO,QAAQ,KAAA,EAAA,EAAS;AAClD,IAAA,MAAM,KAAA,GAAQ,OAAO,KAAK,CAAA;AAC1B,IAAA,KAAA,IAAS,IAAI,KAAK,CAAA,CAAA,CAAA;AAElB,IAAA,IAAI,KAAA,KAAU,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG;AAC/B,MAAA,KAAA,IAAS,GAAA;AAAA,IACX,CAAA,MAAO;AACL,MAAA,KAAA,IAAS,GAAA;AAAA,IACX;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;AAOO,MAAM,kBAAkB,CAAC;AAAA,EAC9B,OAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,KAA2B;AACzB,EAAA,MAAM,cAAc,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,GAAI,OAAA,GAAU,CAAC,OAAO,CAAA;AAC/D,EAAA,IAAI,GAAA,GAAM,yBAAA,CAA0B,SAAA,EAAW,WAAW,CAAA;AAC1D,EAAA,IAAI,YAAY,MAAA,EAAQ;AACtB,IAAA,GAAA,IAAO,CAAA,KAAA,EAAQ,yBAAA,CAA0B,WAAA,EAAa,UAAU,CAAC,CAAA,CAAA;AAAA,EACnE;AACA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,GAAA,IAAO,QAAQ,KAAK,CAAA,CAAA;AAAA,EACtB;AACA,EAAA,OAAO,GAAA;AACT;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultValues.cjs.js","sources":["../../src/service/defaultValues.ts"],"sourcesContent":["export const DEFAULT_MAX_RESULTS_USER_ISSUES = 10;\n"],"names":[],"mappings":";;AAAO,MAAM,+
|
|
1
|
+
{"version":3,"file":"defaultValues.cjs.js","sources":["../../src/service/defaultValues.ts"],"sourcesContent":["export const DEFAULT_MAX_RESULTS_USER_ISSUES = 10;\n"],"names":[],"mappings":";;AAAO,MAAM,+BAAA,GAAkC;;;;"}
|
|
@@ -60,20 +60,21 @@ async function createRouter(options) {
|
|
|
60
60
|
const projects = fullProjectKeys.map(
|
|
61
61
|
(fullProjectKey) => lib.splitProjectKey(config, fullProjectKey)
|
|
62
62
|
);
|
|
63
|
+
const projectResults = await Promise.allSettled(
|
|
64
|
+
projects.map((project) => service.getProjectResponse(project, cache))
|
|
65
|
+
);
|
|
63
66
|
const projectResponses = [];
|
|
64
|
-
for (const
|
|
65
|
-
|
|
66
|
-
const projectData = await service.getProjectResponse(project, cache);
|
|
67
|
-
projectResponses.push(projectData);
|
|
68
|
-
} catch (err) {
|
|
67
|
+
for (const [i, result] of projectResults.entries()) {
|
|
68
|
+
if (result.status === "rejected") {
|
|
69
69
|
logger.error(
|
|
70
|
-
`Could not find Jira project ${
|
|
70
|
+
`Could not find Jira project ${projects[i].fullProjectKey}: ${result.reason?.message ?? result.reason}`
|
|
71
71
|
);
|
|
72
72
|
response.status(404).json({
|
|
73
|
-
error: `Jira project not found with key ${
|
|
73
|
+
error: `Jira project not found with key ${projects[i].fullProjectKey}`
|
|
74
74
|
});
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
|
+
projectResponses.push(result.value);
|
|
77
78
|
}
|
|
78
79
|
let userEntity;
|
|
79
80
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport stream from 'stream';\n\nimport {\n AuthService,\n CacheService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\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 } 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 * 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 * Implementation of Cache Service\n */\n cache: CacheService;\n}\n\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { auth, logger, config, discovery, httpAuth, userInfo, cache } =\n options;\n const catalogClient = new CatalogClient({ discoveryApi: discovery });\n\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 jqlAnnotation,\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 const projectResponses: Project[] = [];\n\n for (const project of projects) {\n try {\n const projectData = await getProjectResponse(project, cache);\n projectResponses.push(projectData);\n } catch (err: any) {\n logger.error(\n `Could not find Jira project ${project.fullProjectKey}: ${err.message}`,\n );\n response.status(404).json({\n error: `Jira project not found with key ${project.fullProjectKey}`,\n });\n return;\n }\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 const instance = projects[0]?.instance;\n\n let components =\n entity.metadata.annotations?.[componentsAnnotation]?.split(',') ?? [];\n\n const jqlValue = entity.metadata.annotations?.[jqlAnnotation] ?? '';\n\n const projectKeys = projects.map(project => project.projectKey);\n let issues = await getIssuesFromFilters(\n projectKeys,\n components,\n filters,\n instance,\n cache,\n jqlValue,\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.length > 0) {\n const componentIssues = await getIssuesFromComponents(\n projectKeys,\n components,\n instance,\n cache,\n jqlValue,\n );\n issues = issues.concat(componentIssues);\n }\n\n const jiraResponse: JiraResponse = {\n project: projectResponses,\n data: issues,\n };\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 const filterName = (request.query?.filterName as string) || 'default';\n\n try {\n const issues = await getUserIssues(\n username,\n maxResults,\n instance,\n cache,\n filterName,\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 return router;\n}\n"],"names":["catalogClient","CatalogClient","Router","express","stringifyEntityRef","getAnnotations","splitProjectKey","getProjectResponse","filters","getDefaultFiltersForUser","getFiltersFromAnnotations","getIssuesFromFilters","getIssuesFromComponents","getAssigneUser","DEFAULT_MAX_RESULTS_USER_ISSUES","issues","getUserIssues","getProjectAvatar","stream"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport stream from 'stream';\n\nimport {\n AuthService,\n CacheService,\n DiscoveryService,\n HttpAuthService,\n LoggerService,\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 } 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 * 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 * Implementation of Cache Service\n */\n cache: CacheService;\n}\n\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { auth, logger, config, discovery, httpAuth, userInfo, cache } =\n options;\n const catalogClient = new CatalogClient({ discoveryApi: discovery });\n\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 jqlAnnotation,\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 const projectResults = await Promise.allSettled(\n projects.map(project => getProjectResponse(project, cache)),\n );\n\n const projectResponses: Project[] = [];\n for (const [i, result] of projectResults.entries()) {\n if (result.status === 'rejected') {\n logger.error(\n `Could not find Jira project ${projects[i].fullProjectKey}: ${\n result.reason?.message ?? result.reason\n }`,\n );\n response.status(404).json({\n error: `Jira project not found with key ${projects[i].fullProjectKey}`,\n });\n return;\n }\n projectResponses.push(result.value);\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 const instance = projects[0]?.instance;\n\n let components =\n entity.metadata.annotations?.[componentsAnnotation]?.split(',') ?? [];\n\n const jqlValue = entity.metadata.annotations?.[jqlAnnotation] ?? '';\n\n const projectKeys = projects.map(project => project.projectKey);\n let issues = await getIssuesFromFilters(\n projectKeys,\n components,\n filters,\n instance,\n cache,\n jqlValue,\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.length > 0) {\n const componentIssues = await getIssuesFromComponents(\n projectKeys,\n components,\n instance,\n cache,\n jqlValue,\n );\n issues = issues.concat(componentIssues);\n }\n\n const jiraResponse: JiraResponse = {\n project: projectResponses,\n data: issues,\n };\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 const filterName = (request.query?.filterName as string) || 'default';\n\n try {\n const issues = await getUserIssues(\n username,\n maxResults,\n instance,\n cache,\n filterName,\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 return router;\n}\n"],"names":["catalogClient","CatalogClient","Router","express","stringifyEntityRef","getAnnotations","splitProjectKey","getProjectResponse","filters","getDefaultFiltersForUser","getFiltersFromAnnotations","getIssuesFromFilters","getIssuesFromComponents","getAssigneUser","DEFAULT_MAX_RESULTS_USER_ISSUES","issues","getUserIssues","getProjectAvatar","stream"],"mappings":"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"}
|
|
@@ -65,39 +65,36 @@ const getUserIssues = async (username, maxResults, config, cache, filterName) =>
|
|
|
65
65
|
});
|
|
66
66
|
};
|
|
67
67
|
const getFiltersFromAnnotations = async (annotations, config) => {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
} catch (err) {
|
|
68
|
+
const results = await Promise.allSettled(
|
|
69
|
+
annotations.map((filter) => api.getFilterById(filter, config))
|
|
70
|
+
);
|
|
71
|
+
return results.map((result, i) => {
|
|
72
|
+
if (result.status === "rejected") {
|
|
74
73
|
console.warn(
|
|
75
|
-
`${
|
|
74
|
+
`${result.reason.message} : Could not find filter with filter id ${annotations[i]}`
|
|
76
75
|
);
|
|
76
|
+
return null;
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
return result.value;
|
|
79
|
+
}).filter((filter) => filter !== null);
|
|
80
80
|
};
|
|
81
81
|
async function getJiraProjectsFromKeys(projectKeys, instance, cache) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (cachedProject) {
|
|
87
|
-
projectInfo = cachedProject;
|
|
88
|
-
} else {
|
|
89
|
-
projectInfo = await api.getProjectInfo({
|
|
82
|
+
return Promise.all(
|
|
83
|
+
projectKeys.map(async (key) => {
|
|
84
|
+
const cachedProject = await cache.get(key);
|
|
85
|
+
const projectInfo = cachedProject ?? await api.getProjectInfo({
|
|
90
86
|
projectKey: key,
|
|
91
87
|
instance});
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
88
|
+
if (!cachedProject) {
|
|
89
|
+
cache.set(key, projectInfo, { ttl: instance.cacheTtl });
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
instance,
|
|
93
|
+
fullProjectKey: projectInfo.key,
|
|
94
|
+
projectKey: projectInfo.key
|
|
95
|
+
};
|
|
96
|
+
})
|
|
97
|
+
);
|
|
101
98
|
}
|
|
102
99
|
const getIssuesFromFilters = async (projectKeys, components, filters, instance, cache, jqlAnnotation) => {
|
|
103
100
|
const projects = await getJiraProjectsFromKeys(projectKeys, instance, cache);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.cjs.js","sources":["../../src/service/service.ts"],"sourcesContent":["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 ttl: project.instance.cacheTtl,\n });\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, { ttl: config.cacheTtl });\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 filterName: string,\n): Promise<Issue[]> => {\n let jql = `assignee = \"${username}\" AND resolution = Unresolved ORDER BY priority DESC, updated DESC`;\n if (filterName !== 'default') {\n for (const filter of config.defaultFilters || []) {\n if (filterName === filter.name) {\n jql = `assignee = \"${username}\" AND ${filter.query}`;\n }\n }\n }\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
|
|
1
|
+
{"version":3,"file":"service.cjs.js","sources":["../../src/service/service.ts"],"sourcesContent":["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 ttl: project.instance.cacheTtl,\n });\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, { ttl: config.cacheTtl });\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 filterName: string,\n): Promise<Issue[]> => {\n let jql = `assignee = \"${username}\" AND resolution = Unresolved ORDER BY priority DESC, updated DESC`;\n if (filterName !== 'default') {\n for (const filter of config.defaultFilters || []) {\n if (filterName === filter.name) {\n jql = `assignee = \"${username}\" AND ${filter.query}`;\n }\n }\n }\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 results = await Promise.allSettled(\n annotations.map(filter => getFilterById(filter, config)),\n );\n\n return results\n .map((result, i) => {\n if (result.status === 'rejected') {\n console.warn(\n `${result.reason.message} : Could not find filter with filter id ${annotations[i]}`,\n );\n return null;\n }\n return result.value;\n })\n .filter((filter): filter is Filter => filter !== null);\n};\nasync function getJiraProjectsFromKeys(\n projectKeys: string[],\n instance: ConfigInstance,\n cache: CacheService,\n): Promise<JiraProject[]> {\n return Promise.all(\n projectKeys.map(async key => {\n const cachedProject = (await cache.get(key)) as Project;\n const projectInfo =\n cachedProject ??\n (await getProjectInfo({\n projectKey: key,\n instance,\n fullProjectKey: '',\n }));\n\n if (!cachedProject) {\n cache.set(key, projectInfo, { ttl: instance.cacheTtl });\n }\n\n return {\n instance,\n fullProjectKey: projectInfo.key,\n projectKey: projectInfo.key,\n };\n }),\n );\n}\nexport const getIssuesFromFilters = async (\n projectKeys: string[],\n components: string[],\n filters: Filter[],\n instance: ConfigInstance,\n cache: CacheService,\n jqlAnnotation?: string,\n): Promise<JiraDataResponse[]> => {\n const projects = await getJiraProjectsFromKeys(projectKeys, instance, cache);\n return await Promise.all(\n filters.map(async filter => {\n const combinedQuery = `${jqlAnnotation ? `(${jqlAnnotation}) AND ` : ''}${\n filter.query\n }`;\n return {\n name: filter.name,\n query: jqlQueryBuilder({\n project: projectKeys,\n components,\n query: combinedQuery,\n }),\n type: 'filter',\n issues: await getIssuesByFilter(projects, components, combinedQuery),\n };\n }),\n );\n};\n\nexport const getIssuesFromComponents = async (\n projectKeys: string[],\n componentAnnotations: string[],\n instance: ConfigInstance,\n cache: CacheService,\n jqlAnnotation?: string,\n): Promise<JiraDataResponse[]> => {\n const projects = await getJiraProjectsFromKeys(projectKeys, instance, cache);\n return await Promise.all(\n componentAnnotations.map(async componentKey => ({\n name: componentKey,\n query: jqlQueryBuilder({\n project: projectKeys,\n components: [componentKey],\n query: jqlQueryBuilder({\n project: projectKeys,\n components: componentAnnotations,\n query: jqlAnnotation,\n }),\n }),\n type: 'component',\n issues: await getIssuesByComponent(projects, componentKey, jqlAnnotation),\n })),\n );\n};\n"],"names":["getProjectInfo","searchJira","getFilterById","jqlQueryBuilder","getIssuesByFilter","getIssuesByComponent"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axis-backstage/plugin-jira-dashboard-backend",
|
|
3
|
-
"version": "6.1.
|
|
3
|
+
"version": "6.1.3",
|
|
4
4
|
"main": "dist/index.cjs.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -32,23 +32,23 @@
|
|
|
32
32
|
"postpack": "backstage-cli package postpack"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@axis-backstage/plugin-jira-dashboard-common": "^1.15.
|
|
36
|
-
"@backstage/backend-defaults": "^0.
|
|
37
|
-
"@backstage/backend-plugin-api": "^1.
|
|
38
|
-
"@backstage/catalog-client": "^1.
|
|
39
|
-
"@backstage/catalog-model": "^1.
|
|
40
|
-
"@backstage/config": "^1.3.
|
|
41
|
-
"@backstage/errors": "^1.
|
|
35
|
+
"@axis-backstage/plugin-jira-dashboard-common": "^1.15.1",
|
|
36
|
+
"@backstage/backend-defaults": "^0.17.0",
|
|
37
|
+
"@backstage/backend-plugin-api": "^1.9.0",
|
|
38
|
+
"@backstage/catalog-client": "^1.15.0",
|
|
39
|
+
"@backstage/catalog-model": "^1.8.0",
|
|
40
|
+
"@backstage/config": "^1.3.7",
|
|
41
|
+
"@backstage/errors": "^1.3.0",
|
|
42
42
|
"@backstage/types": "^1.2.2",
|
|
43
43
|
"express": "^4.17.1",
|
|
44
44
|
"express-promise-router": "^4.1.0",
|
|
45
45
|
"node-fetch": "^2.6.7"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@backstage/backend-test-utils": "^1.
|
|
49
|
-
"@backstage/cli": "^0.
|
|
50
|
-
"@backstage/plugin-auth-backend": "^0.
|
|
51
|
-
"@backstage/plugin-auth-backend-module-guest-provider": "^0.2.
|
|
48
|
+
"@backstage/backend-test-utils": "^1.11.2",
|
|
49
|
+
"@backstage/cli": "^0.36.1",
|
|
50
|
+
"@backstage/plugin-auth-backend": "^0.28.0",
|
|
51
|
+
"@backstage/plugin-auth-backend-module-guest-provider": "^0.2.18",
|
|
52
52
|
"@types/express": "*",
|
|
53
53
|
"@types/supertest": "^2.0.12",
|
|
54
54
|
"msw": "^2.7.3",
|