@axis-backstage/plugin-jira-dashboard-backend 6.1.4 → 6.1.6
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 +18 -0
- package/config.schema.json +252 -0
- package/dist/api.cjs.js +5 -8
- package/dist/api.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/service/router.cjs.js +4 -0
- package/dist/service/router.cjs.js.map +1 -1
- package/package.json +20 -16
- package/config.d.ts +0 -128
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @axis-backstage/plugin-jira-dashboard-backend
|
|
2
2
|
|
|
3
|
+
## 6.1.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7d575b9: Fix URL encoding of JQL query parameters containing URL-reserved characters.
|
|
8
|
+
- b59789b: Use native fetch instead of "node-fetch".
|
|
9
|
+
- 6a30651: Updated to Backstage 1.54.6
|
|
10
|
+
- Updated dependencies [6a30651]
|
|
11
|
+
- @axis-backstage/plugin-jira-dashboard-common@1.15.4
|
|
12
|
+
|
|
13
|
+
## 6.1.5
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- b7492ab: Updated to Backstage 1.53.1
|
|
18
|
+
- Updated dependencies [b7492ab]
|
|
19
|
+
- @axis-backstage/plugin-jira-dashboard-common@1.15.3
|
|
20
|
+
|
|
3
21
|
## 6.1.4
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"jiraDashboard": {
|
|
6
|
+
"anyOf": [
|
|
7
|
+
{
|
|
8
|
+
"type": "object",
|
|
9
|
+
"properties": {
|
|
10
|
+
"token": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "The API token to authenticate towards Jira. It can be found by visiting Atlassians page at https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/",
|
|
13
|
+
"visibility": "secret"
|
|
14
|
+
},
|
|
15
|
+
"headers": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"additionalProperties": {
|
|
18
|
+
"anyOf": [
|
|
19
|
+
{
|
|
20
|
+
"type": "string"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"not": {}
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"visibility": "secret"
|
|
27
|
+
},
|
|
28
|
+
"description": "Optional headers to pass the HTTP requests"
|
|
29
|
+
},
|
|
30
|
+
"baseUrl": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "The base url for Jira in your company, including the API version. For instance: https://jira.se.your-company.com/rest/api/2/'"
|
|
33
|
+
},
|
|
34
|
+
"apiUrl": {
|
|
35
|
+
"type": "string",
|
|
36
|
+
"description": "Optional url for the Jira API, if different from the baseUrl. This can be useful if your Jira instance has a different API endpoint, like if using scoped API tokens. For example: https://api.atlassian.com/ex/jira/7c9c39d8-d07d-43bd-924b-a82397d47f45/rest/api/2/"
|
|
37
|
+
},
|
|
38
|
+
"userEmailSuffix": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"description": "Optional email suffix used for retrieving a specific Jira user in a company. For instance:"
|
|
41
|
+
},
|
|
42
|
+
"annotationPrefix": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"description": "Optional annotation prefix for retrieving a custom annotation. Default value is jira.com",
|
|
45
|
+
"visibility": "frontend"
|
|
46
|
+
},
|
|
47
|
+
"defaultFilters": {
|
|
48
|
+
"type": "array",
|
|
49
|
+
"items": {
|
|
50
|
+
"type": "object",
|
|
51
|
+
"properties": {
|
|
52
|
+
"name": {
|
|
53
|
+
"type": "string"
|
|
54
|
+
},
|
|
55
|
+
"query": {
|
|
56
|
+
"type": "string"
|
|
57
|
+
},
|
|
58
|
+
"shortName": {
|
|
59
|
+
"type": "string"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"required": [
|
|
63
|
+
"name",
|
|
64
|
+
"query",
|
|
65
|
+
"shortName"
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
"description": "Optional default filters for Jira queries"
|
|
69
|
+
},
|
|
70
|
+
"useApiV3": {
|
|
71
|
+
"type": "boolean",
|
|
72
|
+
"description": "Whether to use Jira API v3. Defaults to false for backward compatibility."
|
|
73
|
+
},
|
|
74
|
+
"cacheTtl": {
|
|
75
|
+
"anyOf": [
|
|
76
|
+
{
|
|
77
|
+
"type": "object",
|
|
78
|
+
"properties": {
|
|
79
|
+
"years": {
|
|
80
|
+
"type": "number"
|
|
81
|
+
},
|
|
82
|
+
"months": {
|
|
83
|
+
"type": "number"
|
|
84
|
+
},
|
|
85
|
+
"weeks": {
|
|
86
|
+
"type": "number"
|
|
87
|
+
},
|
|
88
|
+
"days": {
|
|
89
|
+
"type": "number"
|
|
90
|
+
},
|
|
91
|
+
"hours": {
|
|
92
|
+
"type": "number"
|
|
93
|
+
},
|
|
94
|
+
"minutes": {
|
|
95
|
+
"type": "number"
|
|
96
|
+
},
|
|
97
|
+
"seconds": {
|
|
98
|
+
"type": "number"
|
|
99
|
+
},
|
|
100
|
+
"milliseconds": {
|
|
101
|
+
"type": "number"
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"description": "Human friendly durations object."
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"type": "string"
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
"description": "Optional cache TTL, defaults to 1 hour."
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"required": [
|
|
114
|
+
"token",
|
|
115
|
+
"baseUrl"
|
|
116
|
+
]
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"type": "object",
|
|
120
|
+
"properties": {
|
|
121
|
+
"annotationPrefix": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Optional annotation prefix for retrieving a custom annotation. Default value is jira.com",
|
|
124
|
+
"visibility": "frontend"
|
|
125
|
+
},
|
|
126
|
+
"instances": {
|
|
127
|
+
"type": "array",
|
|
128
|
+
"items": {
|
|
129
|
+
"type": "object",
|
|
130
|
+
"properties": {
|
|
131
|
+
"name": {
|
|
132
|
+
"type": "string",
|
|
133
|
+
"description": "Instance name. This is used in entity annotations to refer to the right instance. In entity annotations, this defaults to \"default\"."
|
|
134
|
+
},
|
|
135
|
+
"token": {
|
|
136
|
+
"type": "string",
|
|
137
|
+
"description": "The API token to authenticate towards Jira. It can be found by visiting Atlassians page at https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/",
|
|
138
|
+
"visibility": "secret"
|
|
139
|
+
},
|
|
140
|
+
"headers": {
|
|
141
|
+
"type": "object",
|
|
142
|
+
"additionalProperties": {
|
|
143
|
+
"anyOf": [
|
|
144
|
+
{
|
|
145
|
+
"type": "string"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"not": {}
|
|
149
|
+
}
|
|
150
|
+
],
|
|
151
|
+
"visibility": "secret"
|
|
152
|
+
},
|
|
153
|
+
"description": "Optional headers to pass the HTTP requests"
|
|
154
|
+
},
|
|
155
|
+
"baseUrl": {
|
|
156
|
+
"type": "string",
|
|
157
|
+
"description": "The base url for Jira in your company, including the API version. For instance: https://jira.se.your-company.com/rest/api/2/'"
|
|
158
|
+
},
|
|
159
|
+
"apiUrl": {
|
|
160
|
+
"type": "string",
|
|
161
|
+
"description": "Optional url for the Jira API, if different from the baseUrl. This can be useful if your Jira instance has a different API endpoint, like if using scoped API tokens. For example: https://api.atlassian.com/ex/jira/7c9c39d8-d07d-43bd-924b-a82397d47f45/rest/api/2/"
|
|
162
|
+
},
|
|
163
|
+
"userEmailSuffix": {
|
|
164
|
+
"type": "string",
|
|
165
|
+
"description": "Optional email suffix used for retrieving a specific Jira user in a company. For instance:"
|
|
166
|
+
},
|
|
167
|
+
"defaultFilters": {
|
|
168
|
+
"type": "array",
|
|
169
|
+
"items": {
|
|
170
|
+
"type": "object",
|
|
171
|
+
"properties": {
|
|
172
|
+
"name": {
|
|
173
|
+
"type": "string"
|
|
174
|
+
},
|
|
175
|
+
"query": {
|
|
176
|
+
"type": "string"
|
|
177
|
+
},
|
|
178
|
+
"shortName": {
|
|
179
|
+
"type": "string"
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
"required": [
|
|
183
|
+
"name",
|
|
184
|
+
"query",
|
|
185
|
+
"shortName"
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
"description": "Optional default filters for Jira queries"
|
|
189
|
+
},
|
|
190
|
+
"useApiV3": {
|
|
191
|
+
"type": "boolean",
|
|
192
|
+
"description": "Whether to use Jira API v3. Defaults to false for backward compatibility."
|
|
193
|
+
},
|
|
194
|
+
"cacheTtl": {
|
|
195
|
+
"anyOf": [
|
|
196
|
+
{
|
|
197
|
+
"type": "object",
|
|
198
|
+
"properties": {
|
|
199
|
+
"years": {
|
|
200
|
+
"type": "number"
|
|
201
|
+
},
|
|
202
|
+
"months": {
|
|
203
|
+
"type": "number"
|
|
204
|
+
},
|
|
205
|
+
"weeks": {
|
|
206
|
+
"type": "number"
|
|
207
|
+
},
|
|
208
|
+
"days": {
|
|
209
|
+
"type": "number"
|
|
210
|
+
},
|
|
211
|
+
"hours": {
|
|
212
|
+
"type": "number"
|
|
213
|
+
},
|
|
214
|
+
"minutes": {
|
|
215
|
+
"type": "number"
|
|
216
|
+
},
|
|
217
|
+
"seconds": {
|
|
218
|
+
"type": "number"
|
|
219
|
+
},
|
|
220
|
+
"milliseconds": {
|
|
221
|
+
"type": "number"
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
"description": "Human friendly durations object."
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"type": "string"
|
|
228
|
+
}
|
|
229
|
+
],
|
|
230
|
+
"description": "Optional cache TTL, defaults to 1 hour."
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
"required": [
|
|
234
|
+
"name",
|
|
235
|
+
"token",
|
|
236
|
+
"baseUrl"
|
|
237
|
+
]
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
"required": [
|
|
242
|
+
"instances"
|
|
243
|
+
]
|
|
244
|
+
}
|
|
245
|
+
],
|
|
246
|
+
"description": "Configuration options for the Jira Dashboard plugin"
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
"required": [
|
|
250
|
+
"jiraDashboard"
|
|
251
|
+
]
|
|
252
|
+
}
|
package/dist/api.cjs.js
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var fetch = require('node-fetch');
|
|
4
3
|
var queries = require('./queries.cjs.js');
|
|
5
4
|
var lib = require('./lib.cjs.js');
|
|
6
5
|
var errors = require('@backstage/errors');
|
|
7
6
|
|
|
8
|
-
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
9
|
-
|
|
10
|
-
var fetch__default = /*#__PURE__*/_interopDefaultCompat(fetch);
|
|
11
|
-
|
|
12
7
|
const getProjectInfo = async (project) => {
|
|
13
8
|
const { projectKey, instance } = project;
|
|
14
9
|
const response = await callApi(
|
|
@@ -52,13 +47,15 @@ const getQueryUrl = (instance, jql) => {
|
|
|
52
47
|
if (instance.useApiV3) {
|
|
53
48
|
const baseUrlWithEndpoint2 = `${baseUrl}search/jql`;
|
|
54
49
|
if (jql) {
|
|
55
|
-
return `${baseUrlWithEndpoint2}?jql=${
|
|
50
|
+
return `${baseUrlWithEndpoint2}?jql=${encodeURIComponent(
|
|
51
|
+
jql
|
|
52
|
+
)}&fields=*all`;
|
|
56
53
|
}
|
|
57
54
|
return baseUrlWithEndpoint2;
|
|
58
55
|
}
|
|
59
56
|
const baseUrlWithEndpoint = `${baseUrl}search`;
|
|
60
57
|
if (jql) {
|
|
61
|
-
return `${baseUrlWithEndpoint}?jql=${jql}`;
|
|
58
|
+
return `${baseUrlWithEndpoint}?jql=${encodeURIComponent(jql)}`;
|
|
62
59
|
}
|
|
63
60
|
return baseUrlWithEndpoint;
|
|
64
61
|
};
|
|
@@ -164,7 +161,7 @@ async function callApi(instance, url, init) {
|
|
|
164
161
|
Authorization: instance.token,
|
|
165
162
|
...requestInit.headers
|
|
166
163
|
};
|
|
167
|
-
return
|
|
164
|
+
return fetch(url, requestInit);
|
|
168
165
|
}
|
|
169
166
|
|
|
170
167
|
exports.callApi = callApi;
|
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 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":";;;;;;;;;;;AAcO,MAAM,cAAA,GAAiB,OAC5B,OAAA,KACqB;AACrB,EAAA,MAAM,EAAE,UAAA,EAAY,QAAA,EAAS,GAAI,OAAA;AACjC,EAAA,MAAM,WAAW,MAAM,OAAA;AAAA,IACrB,QAAA;AAAA,IACA,CAAA,EAAGA,aAAA,CAAU,QAAQ,CAAC,WAAW,UAAU,CAAA,CAAA;AAAA,IAC3C;AAAA,MACE,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,MAAA,EAAQ;AAAA;AACV;AACF,GACF;AACA,EAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,IAAA,MAAM,KAAA;AAAA,MACJ,CAAA,gCAAA,EAAmC,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA;AAAA,KAC5E;AAAA,EACF;AAEA,EAAA,MAAM,eAAA,GAAkB,MAAM,QAAA,CAAS,IAAA,EAAK;AAC5C,EAAAC,wBAAA,CAAqB,OAAA,CAAQ,UAAU,eAAe,CAAA;AACtD,EAAA,OAAO,eAAA;AACT;AAEO,MAAM,aAAA,GAAgB,OAC3B,EAAA,EACA,QAAA,KACoB;AACpB,EAAA,MAAM,WAAW,MAAM,OAAA;AAAA,IACrB,QAAA;AAAA,IACA,CAAA,EAAGD,aAAA,CAAU,QAAQ,CAAC,UAAU,EAAE,CAAA,CAAA;AAAA,IAClC;AAAA,MACE,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,MAAA,EAAQ;AAAA;AACV;AACF,GACF;AACA,EAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,IAAA,MAAM,KAAA,CAAM,CAAA,EAAG,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,EAClC;AACA,EAAA,MAAM,YAAA,GAAe,MAAM,QAAA,CAAS,IAAA,EAAK;AACzC,EAAA,OAAO,EAAE,IAAA,EAAM,YAAA,CAAa,IAAA,EAAM,KAAA,EAAO,aAAa,GAAA,EAAI;AAC5D;AAEO,MAAM,WAAA,GAAc,CAAC,QAAA,EAA0B,GAAA,KAAyB;AAC7E,EAAA,MAAM,OAAA,GAAUA,cAAU,QAAQ,CAAA;AAElC,EAAA,IAAI,SAAS,QAAA,EAAU;AACrB,IAAA,MAAME,oBAAAA,GAAsB,GAAG,OAAO,CAAA,UAAA,CAAA;AACtC,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,OAAO,CAAA,EAAGA,oBAAmB,CAAA,KAAA,EAAQ,GAAG,CAAA,YAAA,CAAA;AAAA,IAC1C;AACA,IAAA,OAAOA,oBAAAA;AAAA,EACT;AAEA,EAAA,MAAM,mBAAA,GAAsB,GAAG,OAAO,CAAA,MAAA,CAAA;AACtC,EAAA,IAAI,GAAA,EAAK;AACP,IAAA,OAAO,CAAA,EAAG,mBAAmB,CAAA,KAAA,EAAQ,GAAG,CAAA,CAAA;AAAA,EAC1C;AACA,EAAA,OAAO,mBAAA;AACT;AAEO,MAAM,iBAAA,GAAoB,OAC/B,QAAA,EACA,UAAA,EACA,KAAA,KACqB;AACrB,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AACzB,IAAA,OAAO,EAAC;AAAA,EACV;AAIA,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,QAAA,CAAS,CAAC,CAAA;AAC/B,EAAA,MAAM,WAAA,GAAc,QAAA,CAAS,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,UAAU,CAAA;AAClD,EAAA,MAAM,MAAMC,uBAAA,CAAgB,EAAE,SAAS,WAAA,EAAa,UAAA,EAAY,OAAO,CAAA;AACvE,EAAA,MAAM,QAAA,GAAW,WAAA,CAAY,QAAA,EAAU,GAAG,CAAA;AAE1C,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,QAAA,EAAU,QAAA,EAAU;AAAA,IACjD,MAAA,EAAQ,KAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ;AAAA;AACV,GACD,CAAA,CACE,IAAA,CAAK,CAAA,IAAA,KAAQ,IAAA,CAAK,MAAM,CAAA,CACxB,KAAA,CAAM,MAAM,IAAI,CAAA;AAEnB,EAAA,IAAI,UAAU,aAAA,EAAe;AAC3B,IAAA,MAAM,KAAA;AAAA,MACJ,8BAA8B,GAAG,CAAA,aAAA,EAAgB,QAAA,EAAU,aAAA,GAAgB,CAAC,CAAC,CAAA;AAAA,KAC/E;AAAA,EACF;AAEA,EAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,IAAAC,uBAAA,CAAoB,QAAA,EAAU,SAAS,MAAM,CAAA;AAC7C,IAAA,OAAO,QAAA,CAAS,MAAA;AAAA,EAClB;AAEA,EAAA,OAAO,EAAC;AACV;AA4BO,MAAM,UAAA,GAAa,OACxB,QAAA,EACA,QAAA,EACA,OAAA,KAC8B;AAC9B,EAAA,MAAM,QAAA,GAAW,YAAY,QAAQ,CAAA;AACrC,EAAA,MAAM,WAAA,GAAc,EAAE,GAAA,EAAK,QAAA,EAAU,GAAG,OAAA,EAAQ;AAEhD,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,QAAA,EAAU,QAAA,EAAU;AAAA,IACjD,MAAA,EAAQ,MAAA;AAAA,IACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,WAAW,CAAA;AAAA,IAChC,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,kBAAA;AAAA,MACR,cAAA,EAAgB;AAAA;AAClB,GACD,CAAA;AACD,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,MAAMC,oBAAA,CAAc,YAAA,CAAa,QAAQ,CAAA;AAAA,EACjD;AACA,EAAA,MAAM,YAAA,GAAgB,MAAM,QAAA,CAAS,IAAA,EAAK;AAC1C,EAAAD,uBAAA,CAAoB,QAAA,EAAU,aAAa,MAAM,CAAA;AACjD,EAAA,OAAO,YAAA;AACT;AAEO,MAAM,oBAAA,GAAuB,OAClC,QAAA,EACA,aAAA,EACA,KAAA,KACqB;AAErB,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AACzB,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,WAAA,GAAc,QAAA,CAAS,GAAA,CAAI,CAAA,OAAA,KAAW,QAAQ,UAAU,CAAA;AAC9D,EAAA,MAAM,UAAA,GAAa,cAChB,KAAA,CAAM,GAAG,EACT,GAAA,CAAI,CAAA,SAAA,KAAa,SAAA,CAAU,IAAA,EAAM,CAAA;AAEpC,EAAA,MAAM,MAAMD,uBAAA,CAAgB;AAAA,IAC1B,OAAA,EAAS,WAAA;AAAA,IACT,UAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,QAAA,CAAS,CAAC,CAAA;AAE/B,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,WAAA,CAAY,QAAA,EAAU,GAAG,CAAA;AAC1C,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,QAAA,EAAU,QAAA,EAAU;AAAA,MACjD,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,MAAA,EAAQ;AAAA;AACV,KACD,CAAA,CAAE,IAAA,CAAK,CAAA,IAAA,KAAQ,IAAA,CAAK,MAAM,CAAA;AAE3B,IAAA,IAAI,CAAC,QAAA,CAAS,MAAA,IAAU,QAAA,CAAS,MAAA,CAAO,WAAW,CAAA,EAAG;AACpD,MAAA,OAAO,EAAC;AAAA,IACV;AAEA,IAAAC,uBAAA,CAAoB,QAAA,EAAU,SAAS,MAAM,CAAA;AAC7C,IAAA,OAAO,QAAA,CAAS,MAAA;AAAA,EAClB,SAAS,KAAA,EAAY;AACnB,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,wCAAwC,CAAA,EAAG;AACpE,MAAA,OAAO,EAAC;AAAA,IACV;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AACF;AACA,eAAsB,gBAAA,CAAiB,KAAa,QAAA,EAA0B;AAC5E,EAAA,OAAO,OAAA,CAAQ,UAAU,GAAG,CAAA;AAC9B;AAUO,MAAM,aAAA,GAAgB,OAC3B,QAAA,EACA,QAAA,KACmB;AACnB,EAAA,MAAM,WAAW,MAAM,OAAA;AAAA,IACrB,QAAA;AAAA,IACA,CAAA,EAAGJ,aAAA,CAAU,QAAQ,CAAC,SAAS,QAAQ,CAAA,2BAAA,CAAA;AAAA,IACvC;AAAA,MACE,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,MAAA,EAAQ;AAAA;AACV;AACF,GACF;AACA,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,MAAMK,oBAAA,CAAc,YAAA,CAAa,QAAQ,CAAA;AAAA,EACjD;AAEA,EAAA,MAAM,KAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AACnC,EAAA,OAAO,KAAA;AACT;AASA,eAAsB,OAAA,CACpB,QAAA,EACA,GAAA,EACA,IAAA,EACA;AACA,EAAA,MAAM,WAAA,GAAc,IAAA,IAAQ,EAAE,MAAA,EAAQ,KAAA,EAAM;AAI5C,EAAA,WAAA,CAAY,OAAA,GAAU;AAAA,IACpB,GAAG,QAAA,CAAS,OAAA;AAAA,IACZ,eAAe,QAAA,CAAS,KAAA;AAAA,IACxB,GAAG,WAAA,CAAY;AAAA,GACjB;AACA,EAAA,OAAOC,sBAAA,CAAM,KAAK,WAAW,CAAA;AAC/B;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"api.cjs.js","sources":["../src/api.ts"],"sourcesContent":["import {\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=${encodeURIComponent(\n jql,\n )}&fields=*all`;\n }\n return baseUrlWithEndpoint;\n }\n\n const baseUrlWithEndpoint = `${baseUrl}search`;\n if (jql) {\n return `${baseUrlWithEndpoint}?jql=${encodeURIComponent(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"],"mappings":";;;;;;AAaO,MAAM,cAAA,GAAiB,OAC5B,OAAA,KACqB;AACrB,EAAA,MAAM,EAAE,UAAA,EAAY,QAAA,EAAS,GAAI,OAAA;AACjC,EAAA,MAAM,WAAW,MAAM,OAAA;AAAA,IACrB,QAAA;AAAA,IACA,CAAA,EAAGA,aAAA,CAAU,QAAQ,CAAC,WAAW,UAAU,CAAA,CAAA;AAAA,IAC3C;AAAA,MACE,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,MAAA,EAAQ;AAAA;AACV;AACF,GACF;AACA,EAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,IAAA,MAAM,KAAA;AAAA,MACJ,CAAA,gCAAA,EAAmC,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,SAAS,UAAU,CAAA;AAAA,KAC5E;AAAA,EACF;AAEA,EAAA,MAAM,eAAA,GAAkB,MAAM,QAAA,CAAS,IAAA,EAAK;AAC5C,EAAAC,wBAAA,CAAqB,OAAA,CAAQ,UAAU,eAAe,CAAA;AACtD,EAAA,OAAO,eAAA;AACT;AAEO,MAAM,aAAA,GAAgB,OAC3B,EAAA,EACA,QAAA,KACoB;AACpB,EAAA,MAAM,WAAW,MAAM,OAAA;AAAA,IACrB,QAAA;AAAA,IACA,CAAA,EAAGD,aAAA,CAAU,QAAQ,CAAC,UAAU,EAAE,CAAA,CAAA;AAAA,IAClC;AAAA,MACE,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,MAAA,EAAQ;AAAA;AACV;AACF,GACF;AACA,EAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,IAAA,MAAM,KAAA,CAAM,CAAA,EAAG,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,EAClC;AACA,EAAA,MAAM,YAAA,GAAe,MAAM,QAAA,CAAS,IAAA,EAAK;AACzC,EAAA,OAAO,EAAE,IAAA,EAAM,YAAA,CAAa,IAAA,EAAM,KAAA,EAAO,aAAa,GAAA,EAAI;AAC5D;AAEO,MAAM,WAAA,GAAc,CAAC,QAAA,EAA0B,GAAA,KAAyB;AAC7E,EAAA,MAAM,OAAA,GAAUA,cAAU,QAAQ,CAAA;AAElC,EAAA,IAAI,SAAS,QAAA,EAAU;AACrB,IAAA,MAAME,oBAAAA,GAAsB,GAAG,OAAO,CAAA,UAAA,CAAA;AACtC,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,OAAO,CAAA,EAAGA,oBAAmB,CAAA,KAAA,EAAQ,kBAAA;AAAA,QACnC;AAAA,OACD,CAAA,YAAA,CAAA;AAAA,IACH;AACA,IAAA,OAAOA,oBAAAA;AAAA,EACT;AAEA,EAAA,MAAM,mBAAA,GAAsB,GAAG,OAAO,CAAA,MAAA,CAAA;AACtC,EAAA,IAAI,GAAA,EAAK;AACP,IAAA,OAAO,CAAA,EAAG,mBAAmB,CAAA,KAAA,EAAQ,kBAAA,CAAmB,GAAG,CAAC,CAAA,CAAA;AAAA,EAC9D;AACA,EAAA,OAAO,mBAAA;AACT;AAEO,MAAM,iBAAA,GAAoB,OAC/B,QAAA,EACA,UAAA,EACA,KAAA,KACqB;AACrB,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AACzB,IAAA,OAAO,EAAC;AAAA,EACV;AAIA,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,QAAA,CAAS,CAAC,CAAA;AAC/B,EAAA,MAAM,WAAA,GAAc,QAAA,CAAS,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,UAAU,CAAA;AAClD,EAAA,MAAM,MAAMC,uBAAA,CAAgB,EAAE,SAAS,WAAA,EAAa,UAAA,EAAY,OAAO,CAAA;AACvE,EAAA,MAAM,QAAA,GAAW,WAAA,CAAY,QAAA,EAAU,GAAG,CAAA;AAE1C,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,QAAA,EAAU,QAAA,EAAU;AAAA,IACjD,MAAA,EAAQ,KAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ;AAAA;AACV,GACD,CAAA,CACE,IAAA,CAAK,CAAA,IAAA,KAAQ,IAAA,CAAK,MAAM,CAAA,CACxB,KAAA,CAAM,MAAM,IAAI,CAAA;AAEnB,EAAA,IAAI,UAAU,aAAA,EAAe;AAC3B,IAAA,MAAM,KAAA;AAAA,MACJ,8BAA8B,GAAG,CAAA,aAAA,EAAgB,QAAA,EAAU,aAAA,GAAgB,CAAC,CAAC,CAAA;AAAA,KAC/E;AAAA,EACF;AAEA,EAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,IAAAC,uBAAA,CAAoB,QAAA,EAAU,SAAS,MAAM,CAAA;AAC7C,IAAA,OAAO,QAAA,CAAS,MAAA;AAAA,EAClB;AAEA,EAAA,OAAO,EAAC;AACV;AA4BO,MAAM,UAAA,GAAa,OACxB,QAAA,EACA,QAAA,EACA,OAAA,KAC8B;AAC9B,EAAA,MAAM,QAAA,GAAW,YAAY,QAAQ,CAAA;AACrC,EAAA,MAAM,WAAA,GAAc,EAAE,GAAA,EAAK,QAAA,EAAU,GAAG,OAAA,EAAQ;AAEhD,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,QAAA,EAAU,QAAA,EAAU;AAAA,IACjD,MAAA,EAAQ,MAAA;AAAA,IACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,WAAW,CAAA;AAAA,IAChC,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,kBAAA;AAAA,MACR,cAAA,EAAgB;AAAA;AAClB,GACD,CAAA;AACD,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,MAAMC,oBAAA,CAAc,YAAA,CAAa,QAAQ,CAAA;AAAA,EACjD;AACA,EAAA,MAAM,YAAA,GAAgB,MAAM,QAAA,CAAS,IAAA,EAAK;AAC1C,EAAAD,uBAAA,CAAoB,QAAA,EAAU,aAAa,MAAM,CAAA;AACjD,EAAA,OAAO,YAAA;AACT;AAEO,MAAM,oBAAA,GAAuB,OAClC,QAAA,EACA,aAAA,EACA,KAAA,KACqB;AAErB,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AACzB,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,WAAA,GAAc,QAAA,CAAS,GAAA,CAAI,CAAA,OAAA,KAAW,QAAQ,UAAU,CAAA;AAC9D,EAAA,MAAM,UAAA,GAAa,cAChB,KAAA,CAAM,GAAG,EACT,GAAA,CAAI,CAAA,SAAA,KAAa,SAAA,CAAU,IAAA,EAAM,CAAA;AAEpC,EAAA,MAAM,MAAMD,uBAAA,CAAgB;AAAA,IAC1B,OAAA,EAAS,WAAA;AAAA,IACT,UAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,QAAA,CAAS,CAAC,CAAA;AAE/B,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,WAAA,CAAY,QAAA,EAAU,GAAG,CAAA;AAC1C,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,QAAA,EAAU,QAAA,EAAU;AAAA,MACjD,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,MAAA,EAAQ;AAAA;AACV,KACD,CAAA,CAAE,IAAA,CAAK,CAAA,IAAA,KAAQ,IAAA,CAAK,MAAM,CAAA;AAE3B,IAAA,IAAI,CAAC,QAAA,CAAS,MAAA,IAAU,QAAA,CAAS,MAAA,CAAO,WAAW,CAAA,EAAG;AACpD,MAAA,OAAO,EAAC;AAAA,IACV;AAEA,IAAAC,uBAAA,CAAoB,QAAA,EAAU,SAAS,MAAM,CAAA;AAC7C,IAAA,OAAO,QAAA,CAAS,MAAA;AAAA,EAClB,SAAS,KAAA,EAAY;AACnB,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,wCAAwC,CAAA,EAAG;AACpE,MAAA,OAAO,EAAC;AAAA,IACV;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AACF;AACA,eAAsB,gBAAA,CAAiB,KAAa,QAAA,EAA0B;AAC5E,EAAA,OAAO,OAAA,CAAQ,UAAU,GAAG,CAAA;AAC9B;AAUO,MAAM,aAAA,GAAgB,OAC3B,QAAA,EACA,QAAA,KACmB;AACnB,EAAA,MAAM,WAAW,MAAM,OAAA;AAAA,IACrB,QAAA;AAAA,IACA,CAAA,EAAGJ,aAAA,CAAU,QAAQ,CAAC,SAAS,QAAQ,CAAA,2BAAA,CAAA;AAAA,IACvC;AAAA,MACE,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,MAAA,EAAQ;AAAA;AACV;AACF,GACF;AACA,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,MAAMK,oBAAA,CAAc,YAAA,CAAa,QAAQ,CAAA;AAAA,EACjD;AAEA,EAAA,MAAM,KAAA,GAAS,MAAM,QAAA,CAAS,IAAA,EAAK;AACnC,EAAA,OAAO,KAAA;AACT;AASA,eAAsB,OAAA,CACpB,QAAA,EACA,GAAA,EACA,IAAA,EACA;AACA,EAAA,MAAM,WAAA,GAAc,IAAA,IAAQ,EAAE,MAAA,EAAQ,KAAA,EAAM;AAI5C,EAAA,WAAA,CAAY,OAAA,GAAU;AAAA,IACpB,GAAG,QAAA,CAAS,OAAA;AAAA,IACZ,eAAe,QAAA,CAAS,KAAA;AAAA,IACxB,GAAG,WAAA,CAAY;AAAA,GACjB;AACA,EAAA,OAAO,KAAA,CAAM,KAAK,WAAW,CAAA;AAC/B;;;;;;;;;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
2
2
|
import { RootConfigService } from '@backstage/backend-plugin-api';
|
|
3
|
-
import fetch, { RequestInit } from 'node-fetch';
|
|
4
3
|
import { Filter, JiraQueryResults } from '@axis-backstage/plugin-jira-dashboard-common';
|
|
5
4
|
|
|
6
5
|
/**
|
|
@@ -101,7 +100,7 @@ declare const searchJira: (instance: ConfigInstance, jqlQuery: string, options:
|
|
|
101
100
|
*
|
|
102
101
|
* @public
|
|
103
102
|
*/
|
|
104
|
-
declare function callApi(instance: ConfigInstance, url: string, init?: RequestInit): Promise<
|
|
103
|
+
declare function callApi(instance: ConfigInstance, url: string, init?: RequestInit): Promise<Response>;
|
|
105
104
|
|
|
106
105
|
/**
|
|
107
106
|
* Types for the arguments to the jqlQueryBuilder function.
|
|
@@ -234,6 +234,10 @@ async function createRouter(options) {
|
|
|
234
234
|
const ps = new stream__default.default.PassThrough();
|
|
235
235
|
const val = avatar.headers.get("content-type");
|
|
236
236
|
response.setHeader("content-type", val ?? "");
|
|
237
|
+
if (!avatar.body) {
|
|
238
|
+
response.sendStatus(502);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
237
241
|
stream__default.default.pipeline(avatar.body, ps, (err) => {
|
|
238
242
|
if (err) {
|
|
239
243
|
logger.error(`${err}`);
|
|
@@ -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 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":";;;;;;;;;;;;;;;;;;;AAiEA,eAAsB,aACpB,OAAA,EACyB;AACzB,EAAA,MAAM,EAAE,MAAM,MAAA,EAAQ,MAAA,EAAQ,WAAW,QAAA,EAAU,QAAA,EAAU,OAAM,GACjE,OAAA;AACF,EAAA,MAAMA,kBAAgB,IAAIC,2BAAA,CAAc,EAAE,YAAA,EAAc,WAAW,CAAA;AAEnE,EAAA,MAAA,CAAO,KAAK,qCAAqC,CAAA;AAEjD,EAAA,MAAM,SAASC,uBAAA,EAAO;AACtB,EAAA,MAAA,CAAO,GAAA,CAAIC,wBAAA,CAAQ,IAAA,EAAM,CAAA;AAEzB,EAAA,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,CAAC,CAAA,EAAG,QAAA,KAAa;AACrC,IAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AACnB,IAAA,QAAA,CAAS,IAAA,CAAK,EAAE,MAAA,EAAQ,IAAA,EAAM,CAAA;AAAA,EAChC,CAAC,CAAA;AAED,EAAA,MAAA,CAAO,GAAA;AAAA,IACL,kDAAA;AAAA,IACA,OAAO,SAAS,QAAA,KAAa;AAC3B,MAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,KAAS,OAAA,CAAQ,MAAA;AAC1C,MAAA,MAAM,YAAYC,+BAAA,CAAmB,EAAE,IAAA,EAAM,SAAA,EAAW,MAAM,CAAA;AAC9D,MAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,KAAK,qBAAA,CAAsB;AAAA,QACjD,UAAA,EAAY,MAAM,IAAA,CAAK,wBAAA,EAAyB;AAAA,QAChD,cAAA,EAAgB;AAAA,OACjB,CAAA;AACD,MAAA,MAAM,SAAS,MAAMJ,eAAA,CAAc,eAAe,SAAA,EAAW,EAAE,OAAO,CAAA;AACtE,MAAA,MAAM;AAAA,QACJ,oBAAA;AAAA,QACA,aAAA;AAAA,QACA,oBAAA;AAAA,QACA,iBAAA;AAAA,QACA,wBAAA;AAAA,QACA;AAAA,OACF,GAAIK,mBAAe,MAAM,CAAA;AAEzB,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAA,CAAO,IAAA,CAAK,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAE,CAAA;AAC9C,QAAA,QAAA,CACG,MAAA,CAAO,GAAG,CAAA,CACV,IAAA,CAAK,EAAE,KAAA,EAAO,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAA,EAAI,CAAA;AACrD,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,kBACJ,MAAA,CAAO,QAAA,CAAS,cAAc,oBAAoB,CAAA,EAAG,MAAM,GAAG,CAAA;AAEhE,MAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,QAAA,MAAM,KAAA,GAAQ,gDAAgD,SAAS,CAAA,CAAA;AACvE,QAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,QAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,KAAK,CAAA;AAC/B,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,WAAW,eAAA,CAAgB,GAAA;AAAA,QAAI,CAAA,cAAA,KACnCC,mBAAA,CAAgB,MAAA,EAAQ,cAAc;AAAA,OACxC;AACA,MAAA,MAAM,cAAA,GAAiB,MAAM,OAAA,CAAQ,UAAA;AAAA,QACnC,SAAS,GAAA,CAAI,CAAA,OAAA,KAAWC,0BAAA,CAAmB,OAAA,EAAS,KAAK,CAAC;AAAA,OAC5D;AAEA,MAAA,MAAM,mBAA8B,EAAC;AACrC,MAAA,KAAA,MAAW,CAAC,CAAA,EAAG,MAAM,CAAA,IAAK,cAAA,CAAe,SAAQ,EAAG;AAClD,QAAA,IAAI,MAAA,CAAO,WAAW,UAAA,EAAY;AAChC,UAAA,MAAA,CAAO,KAAA;AAAA,YACL,CAAA,4BAAA,EAA+B,QAAA,CAAS,CAAC,CAAA,CAAE,cAAc,KACvD,MAAA,CAAO,MAAA,EAAQ,OAAA,IAAW,MAAA,CAAO,MACnC,CAAA;AAAA,WACF;AACA,UAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK;AAAA,YACxB,KAAA,EAAO,CAAA,gCAAA,EAAmC,QAAA,CAAS,CAAC,EAAE,cAAc,CAAA;AAAA,WACrE,CAAA;AACD,UAAA;AAAA,QACF;AACA,QAAA,gBAAA,CAAiB,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA,MACpC;AAEA,MAAA,IAAI,UAAA;AAEJ,MAAA,IAAI;AACF,QAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,WAAA,CAAY,OAAA,EAAS;AAAA,UACtD,KAAA,EAAO,CAAC,MAAM;AAAA,SACf,CAAA;AACD,QAAA,MAAM,YAAA,GAAe,YAAY,SAAA,CAAU,aAAA;AAE3C,QAAA,UAAA,GAAc,MAAMP,eAAA,CAAc,cAAA,CAAe,YAAA,EAAc;AAAA,UAC7D;AAAA,SACD,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AACZ,QAAA,MAAA,CAAO,KAAK,8BAA8B,CAAA;AAAA,MAC5C;AAEA,MAAA,IAAIQ,YAAoB,EAAC;AAEzB,MAAA,MAAM,cAAA,GACJ,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,wBAAwB,CAAA;AAExD,MAAAA,SAAA,GAAUC,gCAAA;AAAA,QACR,QAAA,CAAS,CAAC,CAAA,CAAE,QAAA;AAAA,QACZ,UAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAA,MAAM,0BACJ,MAAA,CAAO,QAAA,CAAS,cAAc,iBAAiB,CAAA,EAAG,MAAM,GAAG,CAAA;AAE7D,MAAA,IAAI,uBAAA,EAAyB;AAC3B,QAAAD,SAAA,CAAQ,IAAA;AAAA,UACN,GAAI,MAAME,iCAAA;AAAA,YACR,uBAAA;AAAA,YACA,QAAA,CAAS,CAAC,CAAA,CAAE;AAAA;AACd,SACF;AAAA,MACF;AACA,MAAA,MAAM,QAAA,GAAW,QAAA,CAAS,CAAC,CAAA,EAAG,QAAA;AAE9B,MAAA,IAAI,UAAA,GACF,OAAO,QAAA,CAAS,WAAA,GAAc,oBAAoB,CAAA,EAAG,KAAA,CAAM,GAAG,CAAA,IAAK,EAAC;AAEtE,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,aAAa,CAAA,IAAK,EAAA;AAEjE,MAAA,MAAM,WAAA,GAAc,QAAA,CAAS,GAAA,CAAI,CAAA,OAAA,KAAW,QAAQ,UAAU,CAAA;AAC9D,MAAA,IAAI,SAAS,MAAMC,4BAAA;AAAA,QACjB,WAAA;AAAA,QACA,UAAA;AAAA,QACAH,SAAA;AAAA,QACA,QAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OACF;AAGA,MAAA,UAAA,GAAa,UAAA,CAAW,MAAA;AAAA,QACtB,MAAA,CAAO,SAAS,WAAA,GAAc,yBAAyB,GAAG,KAAA,CAAM,GAAG,KACjE;AAAC,OACL;AAEA,MAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACzB,QAAA,MAAM,kBAAkB,MAAMI,+BAAA;AAAA,UAC5B,WAAA;AAAA,UACA,UAAA;AAAA,UACA,QAAA;AAAA,UACA,KAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,MAAA,GAAS,MAAA,CAAO,OAAO,eAAe,CAAA;AAAA,MACxC;AAEA,MAAA,MAAM,YAAA,GAA6B;AAAA,QACjC,OAAA,EAAS,gBAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACR;AAEA,MAAA,QAAA,CAAS,KAAK,YAAY,CAAA;AAAA,IAC5B;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,GAAA,CAAI,yBAAA,EAA2B,OAAO,OAAA,EAAS,QAAA,KAAa;AACjE,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,KAAK,qBAAA,CAAsB;AAAA,MACjD,UAAA,EAAY,MAAM,IAAA,CAAK,wBAAA,EAAyB;AAAA,MAChD,cAAA,EAAgB;AAAA,KACjB,CAAA;AAED,IAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,WAAA,CAAY,OAAA,EAAS;AAAA,MACtD,KAAA,EAAO,CAAC,MAAM;AAAA,KACf,CAAA;AAGD,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,WAAA,EAAa,MAAM,CAAA,EAAG;AAC1C,MAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AAC5B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,WAAA,CAAY,WAAW,CAAA;AAEnD,IAAA,MAAM,UAAA,GAAc,MAAMZ,eAAA,CAAc,cAAA,CAAe,KAAK,aAAA,EAAe;AAAA,MACzE;AAAA,KACD,CAAA;AAED,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,MAAM,KAAA,GAAQ,CAAA,sCAAA,EAAyC,IAAA,CAAK,aAAa,CAAA,CAAA;AACzE,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,MAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,KAAK,CAAA;AAC/B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,wBAAA,GAA2B,OAAO,QAAA,KAA6B;AACnE,MAAA,MAAM,QAAA,GAAWa,sBAAA,CAAe,QAAA,EAAU,UAAU,CAAA;AAEpD,MAAA,MAAM,UAAA,GAAa,MAAA;AAAA,QACjB,OAAA,CAAQ,MAAM,UAAA,IAAcC;AAAA,OAC9B;AAEA,MAAA,MAAM,UAAA,GAAc,OAAA,CAAQ,KAAA,EAAO,UAAA,IAAyB,SAAA;AAE5D,MAAA,IAAI;AACF,QAAA,MAAMC,UAAS,MAAMC,qBAAA;AAAA,UACnB,QAAA;AAAA,UACA,UAAA;AAAA,UACA,QAAA;AAAA,UACA,KAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,OAAO,EAAE,MAAA,EAAAD,OAAAA,EAAQ,KAAA,EAAO,KAAA,CAAA,EAAU;AAAA,MACpC,SAAS,KAAA,EAAY;AACnB,QAAA,OAAO,EAAE,KAAA,EAAM;AAAA,MACjB;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,UAAA,GAAa,MAAM,OAAA,CAAQ,GAAA;AAAA,MAC/B,MAAA,CACG,cAAa,CACb,GAAA;AAAA,QAAI,CAAA,YAAA,KACH,wBAAA,CAAyB,MAAA,CAAO,WAAA,CAAY,YAAY,CAAC;AAAA;AAC3D,KACJ;AAEA,IAAA,MAAM,SAAS,UAAA,CAAW,OAAA,CAAQ,UAAQ,IAAA,CAAK,MAAA,IAAU,EAAE,CAAA;AAC3D,IAAA,MAAM,MAAA,GAAS,UAAA,CACZ,OAAA,CAAQ,CAAA,IAAA,KAAQ,IAAA,CAAK,KAAK,CAAA,CAC1B,MAAA,CAAO,CAAC,CAAA,KAAkC,CAAC,CAAC,CAAC,CAAA;AAEhD,IAAA,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,IAAK,MAAA,CAAO,WAAW,CAAA,EAAG;AAC5C,MAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,MAAM,CAAA;AAAA,IAClC,CAAA,MAAO;AACL,MAAA,MAAM,QAAA,GACJ,MAAA,CAAO,MAAA,GAAS,CAAA,GACZ;AAAA,EAAA,EAAO,MAAA,CAAO,GAAA,CAAI,CAAA,GAAA,KAAO,GAAA,CAAI,OAAO,CAAA,CAAE,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA,GAClD,CAAA,CAAA,EAAI,MAAA,CAAO,CAAC,EAAE,OAAO,CAAA,CAAA;AAE3B,MAAA,MAAA,CAAO,KAAA,CAAM,CAAA,iCAAA,EAAoC,QAAQ,CAAA,CAAE,CAAA;AAC3D,MAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK;AAAA,QACxB,KAAA,EAAO,oCAAoC,QAAQ,CAAA;AAAA,OACpD,CAAA;AAAA,IACH;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAA,CAAO,GAAA;AAAA,IACL,8CAAA;AAAA,IACA,OAAO,SAAS,QAAA,KAAa;AAC3B,MAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,KAAS,OAAA,CAAQ,MAAA;AAC1C,MAAA,MAAM,YAAYX,+BAAA,CAAmB,EAAE,IAAA,EAAM,SAAA,EAAW,MAAM,CAAA;AAC9D,MAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,KAAK,qBAAA,CAAsB;AAAA,QACjD,UAAA,EAAY,MAAM,IAAA,CAAK,wBAAA,EAAyB;AAAA,QAChD,cAAA,EAAgB;AAAA,OACjB,CAAA;AACD,MAAA,MAAM,SAAS,MAAMJ,eAAA,CAAc,eAAe,SAAA,EAAW,EAAE,OAAO,CAAA;AACtE,MAAA,MAAM,EAAE,oBAAA,EAAqB,GAAIK,kBAAA,CAAe,MAAM,CAAA;AAEtD,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAA,CAAO,IAAA,CAAK,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAE,CAAA;AAC9C,QAAA,QAAA,CACG,MAAA,CAAO,GAAG,CAAA,CACV,IAAA,CAAK,EAAE,KAAA,EAAO,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAA,EAAI,CAAA;AACrD,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,kBACJ,MAAA,CAAO,QAAA,CAAS,cAAc,oBAAoB,CAAA,EAAG,MAAM,GAAG,CAAA;AAEhE,MAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,QAAA,MAAM,KAAA,GAAQ,gDAAgD,SAAS,CAAA,CAAA;AACvE,QAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,QAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,KAAK,CAAA;AAC/B,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,WAAW,eAAA,CAAgB,GAAA;AAAA,QAAI,CAAA,cAAA,KACnCC,mBAAA,CAAgB,MAAA,EAAQ,cAAc;AAAA,OACxC;AAEA,MAAA,MAAM,kBAAkB,MAAMC,0BAAA,CAAmB,QAAA,CAAS,CAAC,GAAG,KAAK,CAAA;AAEnE,MAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,QAAA,MAAA,CAAO,MAAM,gCAAgC,CAAA;AAC7C,QAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK;AAAA,UACxB,KAAA,EAAO,CAAA,sCAAA,EAAyC,QAAA,CAAS,CAAC,EAAE,UAAU,CAAA;AAAA,SACvE,CAAA;AACD,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,UAAA,CAAW,OAAO,CAAA;AAE9C,MAAA,MAAM,SAAS,MAAMU,oBAAA,CAAiB,KAAK,QAAA,CAAS,CAAC,EAAE,QAAQ,CAAA;AAE/D,MAAA,MAAM,EAAA,GAAK,IAAIC,uBAAA,CAAO,WAAA,EAAY;AAClC,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA;AAE7C,MAAA,QAAA,CAAS,SAAA,CAAU,cAAA,EAAgB,GAAA,IAAO,EAAE,CAAA;AAC5C,MAAAA,uBAAA,CAAO,QAAA,CAAS,MAAA,CAAO,IAAA,EAAM,EAAA,EAAI,CAAA,GAAA,KAAO;AACtC,QAAA,IAAI,GAAA,EAAK;AACP,UAAA,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,CAAE,CAAA;AACrB,UAAA,QAAA,CAAS,WAAW,GAAG,CAAA;AAAA,QACzB;AACA,QAAA;AAAA,MACF,CAAC,CAAA;AACD,MAAA,EAAA,CAAG,KAAK,QAAQ,CAAA;AAAA,IAClB;AAAA,GACF;AAEA,EAAA,OAAO,MAAA;AACT;;;;"}
|
|
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 if (!avatar.body) {\n response.sendStatus(502);\n return;\n }\n\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":";;;;;;;;;;;;;;;;;;;AAiEA,eAAsB,aACpB,OAAA,EACyB;AACzB,EAAA,MAAM,EAAE,MAAM,MAAA,EAAQ,MAAA,EAAQ,WAAW,QAAA,EAAU,QAAA,EAAU,OAAM,GACjE,OAAA;AACF,EAAA,MAAMA,kBAAgB,IAAIC,2BAAA,CAAc,EAAE,YAAA,EAAc,WAAW,CAAA;AAEnE,EAAA,MAAA,CAAO,KAAK,qCAAqC,CAAA;AAEjD,EAAA,MAAM,SAASC,uBAAA,EAAO;AACtB,EAAA,MAAA,CAAO,GAAA,CAAIC,wBAAA,CAAQ,IAAA,EAAM,CAAA;AAEzB,EAAA,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,CAAC,CAAA,EAAG,QAAA,KAAa;AACrC,IAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AACnB,IAAA,QAAA,CAAS,IAAA,CAAK,EAAE,MAAA,EAAQ,IAAA,EAAM,CAAA;AAAA,EAChC,CAAC,CAAA;AAED,EAAA,MAAA,CAAO,GAAA;AAAA,IACL,kDAAA;AAAA,IACA,OAAO,SAAS,QAAA,KAAa;AAC3B,MAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,KAAS,OAAA,CAAQ,MAAA;AAC1C,MAAA,MAAM,YAAYC,+BAAA,CAAmB,EAAE,IAAA,EAAM,SAAA,EAAW,MAAM,CAAA;AAC9D,MAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,KAAK,qBAAA,CAAsB;AAAA,QACjD,UAAA,EAAY,MAAM,IAAA,CAAK,wBAAA,EAAyB;AAAA,QAChD,cAAA,EAAgB;AAAA,OACjB,CAAA;AACD,MAAA,MAAM,SAAS,MAAMJ,eAAA,CAAc,eAAe,SAAA,EAAW,EAAE,OAAO,CAAA;AACtE,MAAA,MAAM;AAAA,QACJ,oBAAA;AAAA,QACA,aAAA;AAAA,QACA,oBAAA;AAAA,QACA,iBAAA;AAAA,QACA,wBAAA;AAAA,QACA;AAAA,OACF,GAAIK,mBAAe,MAAM,CAAA;AAEzB,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAA,CAAO,IAAA,CAAK,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAE,CAAA;AAC9C,QAAA,QAAA,CACG,MAAA,CAAO,GAAG,CAAA,CACV,IAAA,CAAK,EAAE,KAAA,EAAO,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAA,EAAI,CAAA;AACrD,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,kBACJ,MAAA,CAAO,QAAA,CAAS,cAAc,oBAAoB,CAAA,EAAG,MAAM,GAAG,CAAA;AAEhE,MAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,QAAA,MAAM,KAAA,GAAQ,gDAAgD,SAAS,CAAA,CAAA;AACvE,QAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,QAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,KAAK,CAAA;AAC/B,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,WAAW,eAAA,CAAgB,GAAA;AAAA,QAAI,CAAA,cAAA,KACnCC,mBAAA,CAAgB,MAAA,EAAQ,cAAc;AAAA,OACxC;AACA,MAAA,MAAM,cAAA,GAAiB,MAAM,OAAA,CAAQ,UAAA;AAAA,QACnC,SAAS,GAAA,CAAI,CAAA,OAAA,KAAWC,0BAAA,CAAmB,OAAA,EAAS,KAAK,CAAC;AAAA,OAC5D;AAEA,MAAA,MAAM,mBAA8B,EAAC;AACrC,MAAA,KAAA,MAAW,CAAC,CAAA,EAAG,MAAM,CAAA,IAAK,cAAA,CAAe,SAAQ,EAAG;AAClD,QAAA,IAAI,MAAA,CAAO,WAAW,UAAA,EAAY;AAChC,UAAA,MAAA,CAAO,KAAA;AAAA,YACL,CAAA,4BAAA,EAA+B,QAAA,CAAS,CAAC,CAAA,CAAE,cAAc,KACvD,MAAA,CAAO,MAAA,EAAQ,OAAA,IAAW,MAAA,CAAO,MACnC,CAAA;AAAA,WACF;AACA,UAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK;AAAA,YACxB,KAAA,EAAO,CAAA,gCAAA,EAAmC,QAAA,CAAS,CAAC,EAAE,cAAc,CAAA;AAAA,WACrE,CAAA;AACD,UAAA;AAAA,QACF;AACA,QAAA,gBAAA,CAAiB,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA,MACpC;AAEA,MAAA,IAAI,UAAA;AAEJ,MAAA,IAAI;AACF,QAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,WAAA,CAAY,OAAA,EAAS;AAAA,UACtD,KAAA,EAAO,CAAC,MAAM;AAAA,SACf,CAAA;AACD,QAAA,MAAM,YAAA,GAAe,YAAY,SAAA,CAAU,aAAA;AAE3C,QAAA,UAAA,GAAc,MAAMP,eAAA,CAAc,cAAA,CAAe,YAAA,EAAc;AAAA,UAC7D;AAAA,SACD,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AACZ,QAAA,MAAA,CAAO,KAAK,8BAA8B,CAAA;AAAA,MAC5C;AAEA,MAAA,IAAIQ,YAAoB,EAAC;AAEzB,MAAA,MAAM,cAAA,GACJ,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,wBAAwB,CAAA;AAExD,MAAAA,SAAA,GAAUC,gCAAA;AAAA,QACR,QAAA,CAAS,CAAC,CAAA,CAAE,QAAA;AAAA,QACZ,UAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAA,MAAM,0BACJ,MAAA,CAAO,QAAA,CAAS,cAAc,iBAAiB,CAAA,EAAG,MAAM,GAAG,CAAA;AAE7D,MAAA,IAAI,uBAAA,EAAyB;AAC3B,QAAAD,SAAA,CAAQ,IAAA;AAAA,UACN,GAAI,MAAME,iCAAA;AAAA,YACR,uBAAA;AAAA,YACA,QAAA,CAAS,CAAC,CAAA,CAAE;AAAA;AACd,SACF;AAAA,MACF;AACA,MAAA,MAAM,QAAA,GAAW,QAAA,CAAS,CAAC,CAAA,EAAG,QAAA;AAE9B,MAAA,IAAI,UAAA,GACF,OAAO,QAAA,CAAS,WAAA,GAAc,oBAAoB,CAAA,EAAG,KAAA,CAAM,GAAG,CAAA,IAAK,EAAC;AAEtE,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,aAAa,CAAA,IAAK,EAAA;AAEjE,MAAA,MAAM,WAAA,GAAc,QAAA,CAAS,GAAA,CAAI,CAAA,OAAA,KAAW,QAAQ,UAAU,CAAA;AAC9D,MAAA,IAAI,SAAS,MAAMC,4BAAA;AAAA,QACjB,WAAA;AAAA,QACA,UAAA;AAAA,QACAH,SAAA;AAAA,QACA,QAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OACF;AAGA,MAAA,UAAA,GAAa,UAAA,CAAW,MAAA;AAAA,QACtB,MAAA,CAAO,SAAS,WAAA,GAAc,yBAAyB,GAAG,KAAA,CAAM,GAAG,KACjE;AAAC,OACL;AAEA,MAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACzB,QAAA,MAAM,kBAAkB,MAAMI,+BAAA;AAAA,UAC5B,WAAA;AAAA,UACA,UAAA;AAAA,UACA,QAAA;AAAA,UACA,KAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,MAAA,GAAS,MAAA,CAAO,OAAO,eAAe,CAAA;AAAA,MACxC;AAEA,MAAA,MAAM,YAAA,GAA6B;AAAA,QACjC,OAAA,EAAS,gBAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACR;AAEA,MAAA,QAAA,CAAS,KAAK,YAAY,CAAA;AAAA,IAC5B;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,GAAA,CAAI,yBAAA,EAA2B,OAAO,OAAA,EAAS,QAAA,KAAa;AACjE,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,KAAK,qBAAA,CAAsB;AAAA,MACjD,UAAA,EAAY,MAAM,IAAA,CAAK,wBAAA,EAAyB;AAAA,MAChD,cAAA,EAAgB;AAAA,KACjB,CAAA;AAED,IAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,WAAA,CAAY,OAAA,EAAS;AAAA,MACtD,KAAA,EAAO,CAAC,MAAM;AAAA,KACf,CAAA;AAGD,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,WAAA,EAAa,MAAM,CAAA,EAAG;AAC1C,MAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AAC5B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,WAAA,CAAY,WAAW,CAAA;AAEnD,IAAA,MAAM,UAAA,GAAc,MAAMZ,eAAA,CAAc,cAAA,CAAe,KAAK,aAAA,EAAe;AAAA,MACzE;AAAA,KACD,CAAA;AAED,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,MAAM,KAAA,GAAQ,CAAA,sCAAA,EAAyC,IAAA,CAAK,aAAa,CAAA,CAAA;AACzE,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,MAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,KAAK,CAAA;AAC/B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,wBAAA,GAA2B,OAAO,QAAA,KAA6B;AACnE,MAAA,MAAM,QAAA,GAAWa,sBAAA,CAAe,QAAA,EAAU,UAAU,CAAA;AAEpD,MAAA,MAAM,UAAA,GAAa,MAAA;AAAA,QACjB,OAAA,CAAQ,MAAM,UAAA,IAAcC;AAAA,OAC9B;AAEA,MAAA,MAAM,UAAA,GAAc,OAAA,CAAQ,KAAA,EAAO,UAAA,IAAyB,SAAA;AAE5D,MAAA,IAAI;AACF,QAAA,MAAMC,UAAS,MAAMC,qBAAA;AAAA,UACnB,QAAA;AAAA,UACA,UAAA;AAAA,UACA,QAAA;AAAA,UACA,KAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,OAAO,EAAE,MAAA,EAAAD,OAAAA,EAAQ,KAAA,EAAO,KAAA,CAAA,EAAU;AAAA,MACpC,SAAS,KAAA,EAAY;AACnB,QAAA,OAAO,EAAE,KAAA,EAAM;AAAA,MACjB;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,UAAA,GAAa,MAAM,OAAA,CAAQ,GAAA;AAAA,MAC/B,MAAA,CACG,cAAa,CACb,GAAA;AAAA,QAAI,CAAA,YAAA,KACH,wBAAA,CAAyB,MAAA,CAAO,WAAA,CAAY,YAAY,CAAC;AAAA;AAC3D,KACJ;AAEA,IAAA,MAAM,SAAS,UAAA,CAAW,OAAA,CAAQ,UAAQ,IAAA,CAAK,MAAA,IAAU,EAAE,CAAA;AAC3D,IAAA,MAAM,MAAA,GAAS,UAAA,CACZ,OAAA,CAAQ,CAAA,IAAA,KAAQ,IAAA,CAAK,KAAK,CAAA,CAC1B,MAAA,CAAO,CAAC,CAAA,KAAkC,CAAC,CAAC,CAAC,CAAA;AAEhD,IAAA,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,IAAK,MAAA,CAAO,WAAW,CAAA,EAAG;AAC5C,MAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,MAAM,CAAA;AAAA,IAClC,CAAA,MAAO;AACL,MAAA,MAAM,QAAA,GACJ,MAAA,CAAO,MAAA,GAAS,CAAA,GACZ;AAAA,EAAA,EAAO,MAAA,CAAO,GAAA,CAAI,CAAA,GAAA,KAAO,GAAA,CAAI,OAAO,CAAA,CAAE,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA,GAClD,CAAA,CAAA,EAAI,MAAA,CAAO,CAAC,EAAE,OAAO,CAAA,CAAA;AAE3B,MAAA,MAAA,CAAO,KAAA,CAAM,CAAA,iCAAA,EAAoC,QAAQ,CAAA,CAAE,CAAA;AAC3D,MAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK;AAAA,QACxB,KAAA,EAAO,oCAAoC,QAAQ,CAAA;AAAA,OACpD,CAAA;AAAA,IACH;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAA,CAAO,GAAA;AAAA,IACL,8CAAA;AAAA,IACA,OAAO,SAAS,QAAA,KAAa;AAC3B,MAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,KAAS,OAAA,CAAQ,MAAA;AAC1C,MAAA,MAAM,YAAYX,+BAAA,CAAmB,EAAE,IAAA,EAAM,SAAA,EAAW,MAAM,CAAA;AAC9D,MAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,KAAK,qBAAA,CAAsB;AAAA,QACjD,UAAA,EAAY,MAAM,IAAA,CAAK,wBAAA,EAAyB;AAAA,QAChD,cAAA,EAAgB;AAAA,OACjB,CAAA;AACD,MAAA,MAAM,SAAS,MAAMJ,eAAA,CAAc,eAAe,SAAA,EAAW,EAAE,OAAO,CAAA;AACtE,MAAA,MAAM,EAAE,oBAAA,EAAqB,GAAIK,kBAAA,CAAe,MAAM,CAAA;AAEtD,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAA,CAAO,IAAA,CAAK,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAE,CAAA;AAC9C,QAAA,QAAA,CACG,MAAA,CAAO,GAAG,CAAA,CACV,IAAA,CAAK,EAAE,KAAA,EAAO,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAA,EAAI,CAAA;AACrD,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,kBACJ,MAAA,CAAO,QAAA,CAAS,cAAc,oBAAoB,CAAA,EAAG,MAAM,GAAG,CAAA;AAEhE,MAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,QAAA,MAAM,KAAA,GAAQ,gDAAgD,SAAS,CAAA,CAAA;AACvE,QAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,QAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,KAAK,CAAA;AAC/B,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,WAAW,eAAA,CAAgB,GAAA;AAAA,QAAI,CAAA,cAAA,KACnCC,mBAAA,CAAgB,MAAA,EAAQ,cAAc;AAAA,OACxC;AAEA,MAAA,MAAM,kBAAkB,MAAMC,0BAAA,CAAmB,QAAA,CAAS,CAAC,GAAG,KAAK,CAAA;AAEnE,MAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,QAAA,MAAA,CAAO,MAAM,gCAAgC,CAAA;AAC7C,QAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK;AAAA,UACxB,KAAA,EAAO,CAAA,sCAAA,EAAyC,QAAA,CAAS,CAAC,EAAE,UAAU,CAAA;AAAA,SACvE,CAAA;AACD,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,UAAA,CAAW,OAAO,CAAA;AAE9C,MAAA,MAAM,SAAS,MAAMU,oBAAA,CAAiB,KAAK,QAAA,CAAS,CAAC,EAAE,QAAQ,CAAA;AAE/D,MAAA,MAAM,EAAA,GAAK,IAAIC,uBAAA,CAAO,WAAA,EAAY;AAClC,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA;AAE7C,MAAA,QAAA,CAAS,SAAA,CAAU,cAAA,EAAgB,GAAA,IAAO,EAAE,CAAA;AAC5C,MAAA,IAAI,CAAC,OAAO,IAAA,EAAM;AAChB,QAAA,QAAA,CAAS,WAAW,GAAG,CAAA;AACvB,QAAA;AAAA,MACF;AAEA,MAAAA,uBAAA,CAAO,QAAA,CAAS,MAAA,CAAO,IAAA,EAAM,EAAA,EAAI,CAAA,GAAA,KAAO;AACtC,QAAA,IAAI,GAAA,EAAK;AACP,UAAA,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,CAAE,CAAA;AACrB,UAAA,QAAA,CAAS,WAAW,GAAG,CAAA;AAAA,QACzB;AACA,QAAA;AAAA,MACF,CAAC,CAAA;AACD,MAAA,EAAA,CAAG,KAAK,QAAQ,CAAA;AAAA,IAClB;AAAA,GACF;AAEA,EAAA,OAAO,MAAA;AACT;;;;"}
|
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.6",
|
|
4
4
|
"main": "dist/index.cjs.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
"types": "dist/index.d.ts",
|
|
11
11
|
"directory": "_release/package"
|
|
12
12
|
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/AxisCommunications/backstage-plugins",
|
|
16
|
+
"directory": "plugins/jira-dashboard-backend"
|
|
17
|
+
},
|
|
13
18
|
"backstage": {
|
|
14
19
|
"role": "backend-plugin",
|
|
15
20
|
"pluginId": "jira-dashboard",
|
|
@@ -32,33 +37,32 @@
|
|
|
32
37
|
"postpack": "backstage-cli package postpack"
|
|
33
38
|
},
|
|
34
39
|
"dependencies": {
|
|
35
|
-
"@axis-backstage/plugin-jira-dashboard-common": "^1.15.
|
|
36
|
-
"@backstage/backend-defaults": "^0.17.
|
|
37
|
-
"@backstage/backend-plugin-api": "^1.
|
|
38
|
-
"@backstage/catalog-client": "^1.16.
|
|
39
|
-
"@backstage/catalog-model": "^1.
|
|
40
|
+
"@axis-backstage/plugin-jira-dashboard-common": "^1.15.4",
|
|
41
|
+
"@backstage/backend-defaults": "^0.17.8",
|
|
42
|
+
"@backstage/backend-plugin-api": "^1.10.0",
|
|
43
|
+
"@backstage/catalog-client": "^1.16.1",
|
|
44
|
+
"@backstage/catalog-model": "^1.10.0",
|
|
40
45
|
"@backstage/config": "^1.3.8",
|
|
41
46
|
"@backstage/errors": "^1.3.1",
|
|
42
47
|
"@backstage/types": "^1.2.2",
|
|
43
48
|
"express": "^4.17.1",
|
|
44
|
-
"express-promise-router": "^4.1.0"
|
|
45
|
-
"node-fetch": "^2.6.7"
|
|
49
|
+
"express-promise-router": "^4.1.0"
|
|
46
50
|
},
|
|
47
51
|
"devDependencies": {
|
|
48
|
-
"@backstage/backend-test-utils": "^1.11.
|
|
49
|
-
"@backstage/cli": "^0.36.
|
|
50
|
-
"@backstage/plugin-auth-backend": "^0.
|
|
51
|
-
"@backstage/plugin-auth-backend-module-guest-provider": "^0.2.
|
|
52
|
+
"@backstage/backend-test-utils": "^1.11.6",
|
|
53
|
+
"@backstage/cli": "^0.36.5",
|
|
54
|
+
"@backstage/plugin-auth-backend": "^0.30.0",
|
|
55
|
+
"@backstage/plugin-auth-backend-module-guest-provider": "^0.2.22",
|
|
52
56
|
"@types/express": "*",
|
|
53
|
-
"@types/supertest": "^
|
|
57
|
+
"@types/supertest": "^7.0.0",
|
|
54
58
|
"msw": "^2.7.3",
|
|
55
|
-
"supertest": "^
|
|
59
|
+
"supertest": "^7.0.0"
|
|
56
60
|
},
|
|
57
61
|
"files": [
|
|
58
62
|
"dist",
|
|
59
|
-
"config.
|
|
63
|
+
"config.schema.json"
|
|
60
64
|
],
|
|
61
|
-
"configSchema": "config.
|
|
65
|
+
"configSchema": "config.schema.json",
|
|
62
66
|
"typesVersions": {
|
|
63
67
|
"*": {
|
|
64
68
|
"package.json": [
|
package/config.d.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { HumanDuration } from '@backstage/types';
|
|
2
|
-
|
|
3
|
-
export interface Config {
|
|
4
|
-
/**
|
|
5
|
-
* Configuration options for the Jira Dashboard plugin
|
|
6
|
-
*/
|
|
7
|
-
jiraDashboard:
|
|
8
|
-
| {
|
|
9
|
-
/**
|
|
10
|
-
* The API token to authenticate towards Jira. It can be found by visiting Atlassians page at https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/
|
|
11
|
-
* @visibility secret
|
|
12
|
-
*/
|
|
13
|
-
token: string;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Optional headers to pass the HTTP requests
|
|
17
|
-
*/
|
|
18
|
-
headers?: {
|
|
19
|
-
/** @visibility secret */
|
|
20
|
-
[key: string]: string | undefined;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* The base url for Jira in your company, including the API version. For instance: https://jira.se.your-company.com/rest/api/2/'
|
|
25
|
-
*/
|
|
26
|
-
baseUrl: string;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Optional url for the Jira API, if different from the baseUrl. This can be useful if your Jira instance has a different API endpoint, like if using scoped API tokens. For example: https://api.atlassian.com/ex/jira/7c9c39d8-d07d-43bd-924b-a82397d47f45/rest/api/2/
|
|
30
|
-
*/
|
|
31
|
-
apiUrl?: string;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Optional email suffix used for retrieving a specific Jira user in a company. For instance: @your-company.com. If not provided, the user entity profile email is used instead.
|
|
35
|
-
*/
|
|
36
|
-
userEmailSuffix?: string;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Optional annotation prefix for retrieving a custom annotation. Default value is jira.com
|
|
40
|
-
* @visibility frontend
|
|
41
|
-
*/
|
|
42
|
-
annotationPrefix?: string;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Optional default filters for Jira queries
|
|
46
|
-
*/
|
|
47
|
-
defaultFilters?: {
|
|
48
|
-
name: string;
|
|
49
|
-
query: string;
|
|
50
|
-
shortName: string;
|
|
51
|
-
}[];
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Whether to use Jira API v3. Defaults to false for backward compatibility.
|
|
55
|
-
*/
|
|
56
|
-
useApiV3?: boolean;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Optional cache TTL, defaults to 1 hour.
|
|
60
|
-
*/
|
|
61
|
-
cacheTtl?: HumanDuration | string;
|
|
62
|
-
|
|
63
|
-
// Type helper
|
|
64
|
-
instances?: never;
|
|
65
|
-
}
|
|
66
|
-
| {
|
|
67
|
-
/**
|
|
68
|
-
* Optional annotation prefix for retrieving a custom annotation. Default value is jira.com
|
|
69
|
-
* @visibility frontend
|
|
70
|
-
*/
|
|
71
|
-
annotationPrefix?: string;
|
|
72
|
-
|
|
73
|
-
instances: {
|
|
74
|
-
/**
|
|
75
|
-
* Instance name. This is used in entity annotations to refer to the right instance. In entity annotations, this defaults to "default".
|
|
76
|
-
*/
|
|
77
|
-
name: string;
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* The API token to authenticate towards Jira. It can be found by visiting Atlassians page at https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/
|
|
81
|
-
* @visibility secret
|
|
82
|
-
*/
|
|
83
|
-
token: string;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Optional headers to pass the HTTP requests
|
|
87
|
-
*/
|
|
88
|
-
headers?: {
|
|
89
|
-
/** @visibility secret */
|
|
90
|
-
[key: string]: string | undefined;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* The base url for Jira in your company, including the API version. For instance: https://jira.se.your-company.com/rest/api/2/'
|
|
95
|
-
*/
|
|
96
|
-
baseUrl: string;
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Optional url for the Jira API, if different from the baseUrl. This can be useful if your Jira instance has a different API endpoint, like if using scoped API tokens. For example: https://api.atlassian.com/ex/jira/7c9c39d8-d07d-43bd-924b-a82397d47f45/rest/api/2/
|
|
100
|
-
*/
|
|
101
|
-
apiUrl?: string;
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Optional email suffix used for retrieving a specific Jira user in a company. For instance: @your-company.com. If not provided, the user entity profile email is used instead.
|
|
105
|
-
*/
|
|
106
|
-
userEmailSuffix?: string;
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Optional default filters for Jira queries
|
|
110
|
-
*/
|
|
111
|
-
defaultFilters?: {
|
|
112
|
-
name: string;
|
|
113
|
-
query: string;
|
|
114
|
-
shortName: string;
|
|
115
|
-
}[];
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Whether to use Jira API v3. Defaults to false for backward compatibility.
|
|
119
|
-
*/
|
|
120
|
-
useApiV3?: boolean;
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Optional cache TTL, defaults to 1 hour.
|
|
124
|
-
*/
|
|
125
|
-
cacheTtl?: HumanDuration | string;
|
|
126
|
-
}[];
|
|
127
|
-
};
|
|
128
|
-
}
|