src/jira.js
import _request from 'postman-request';
import url from 'url';
function request(uri, options) {
return new Promise((resolve, reject) => {
_request(uri, options, (err, httpResponse) => {
if (err) {
reject(err);
} else {
// for compatibility with request-promise
resolve(httpResponse.body);
}
});
});
}
/**
* @name JiraApi
* @class
* Wrapper for the JIRA Rest Api
* https://docs.atlassian.com/jira/REST/6.4.8/
*/
export default class JiraApi {
/**
* @constructor
* @function
* @param {JiraApiOptions} options
*/
constructor(options) {
this.protocol = options.protocol || 'http';
this.host = options.host;
this.port = options.port || null;
this.apiVersion = options.apiVersion || '2';
this.base = options.base || '';
this.intermediatePath = options.intermediatePath;
this.strictSSL = options.hasOwnProperty('strictSSL') ? options.strictSSL : true;
// This is so we can fake during unit tests
this.request = options.request || request;
this.webhookVersion = options.webHookVersion || '1.0';
this.greenhopperVersion = options.greenhopperVersion || '1.0';
this.baseOptions = {};
if (options.ca) {
this.baseOptions.ca = options.ca;
}
if (options.oauth && options.oauth.consumer_key && options.oauth.access_token) {
this.baseOptions.oauth = {
consumer_key: options.oauth.consumer_key,
consumer_secret: options.oauth.consumer_secret,
token: options.oauth.access_token,
token_secret: options.oauth.access_token_secret,
signature_method: options.oauth.signature_method || 'RSA-SHA1',
};
} else if (options.bearer) {
this.baseOptions.auth = {
user: '',
pass: '',
sendImmediately: true,
bearer: options.bearer,
};
} else if (options.username && options.password) {
this.baseOptions.auth = {
user: options.username,
pass: options.password,
};
}
if (options.timeout) {
this.baseOptions.timeout = options.timeout;
}
}
/**
* @typedef JiraApiOptions
* @type {object}
* @property {string} [protocol=http] - What protocol to use to connect to
* jira? Ex: http|https
* @property {string} host - What host is this tool connecting to for the jira
* instance? Ex: jira.somehost.com
* @property {string} [port] - What port is this tool connecting to jira with? Only needed for
* none standard ports. Ex: 8080, 3000, etc
* @property {string} [username] - Specify a username for this tool to authenticate all
* requests with.
* @property {string} [password] - Specify a password for this tool to authenticate all
* requests with. Cloud users need to generate an [API token](https://confluence.atlassian.com/cloud/api-tokens-938839638.html) for this value.
* @property {string} [apiVersion=2] - What version of the jira rest api is the instance the
* tool is connecting to?
* @property {string} [base] - What other url parts exist, if any, before the rest/api/
* section?
* @property {string} [intermediatePath] - If specified, overwrites the default rest/api/version
* section of the uri
* @property {boolean} [strictSSL=true] - Does this tool require each request to be
* authenticated? Defaults to true.
* @property {function} [request] - What method does this tool use to make its requests?
* Defaults to request from request-promise
* @property {number} [timeout] - Integer containing the number of milliseconds to wait for a
* server to send response headers (and start the response body) before aborting the request. Note
* that if the underlying TCP connection cannot be established, the OS-wide TCP connection timeout
* will overrule the timeout option ([the default in Linux can be anywhere from 20-120 *
* seconds](http://www.sekuda.com/overriding_the_default_linux_kernel_20_second_tcp_socket_connect_timeout)).
* @property {string} [webhookVersion=1.0] - What webhook version does this api wrapper need to
* hit?
* @property {string} [greenhopperVersion=1.0] - What webhook version does this api wrapper need
* to hit?
* @property {string} [ca] - Specify a CA certificate
* @property {OAuth} [oauth] - Specify an OAuth object for this tool to authenticate all requests
* using OAuth.
* @property {string} [bearer] - Specify an OAuth bearer token to authenticate all requests with.
*/
/**
* @typedef OAuth
* @type {object}
* @property {string} consumer_key - The consumer entered in Jira Preferences.
* @property {string} consumer_secret - The private RSA file.
* @property {string} access_token - The generated access token.
* @property {string} access_token_secret - The generated access toke secret.
* @property {string} signature_method [signature_method=RSA-SHA1] - OAuth signurate methode
* Possible values RSA-SHA1, HMAC-SHA1, PLAINTEXT. Jira Cloud supports only RSA-SHA1.
*/
/**
* @typedef {object} UriOptions
* @property {string} pathname - The url after the specific functions path
* @property {object} [query] - An object of all query parameters
* @property {string} [intermediatePath] - Overwrites with specified path
*/
/**
* @name makeRequestHeader
* @function
* Creates a requestOptions object based on the default template for one
* @param {string} uri
* @param {object} [options] - an object containing fields and formatting how the
*/
makeRequestHeader(uri, options = {}) {
return {
rejectUnauthorized: this.strictSSL,
method: options.method || 'GET',
uri,
json: true,
...options,
};
}
/**
* @typedef makeRequestHeaderOptions
* @type {object}
* @property {string} [method] - HTTP Request Method. ie GET, POST, PUT, DELETE
*/
/**
* @name makeUri
* @function
* Creates a URI object for a given pathname
* @param {object} [options] - an object containing path information
*/
makeUri({
pathname, query, intermediatePath, encode = false,
}) {
const intermediateToUse = this.intermediatePath || intermediatePath;
const tempPath = intermediateToUse || `/rest/api/${this.apiVersion}`;
const uri = url.format({
protocol: this.protocol,
hostname: this.host,
port: this.port,
pathname: `${this.base}${tempPath}${pathname}`,
query,
});
return encode ? encodeURI(uri) : decodeURIComponent(uri);
}
/**
* @typedef makeUriOptions
* @type {object}
* @property {string} pathname - The url after the /rest/api/version
* @property {object} query - a query object
* @property {string} intermediatePath - If specified will overwrite the /rest/api/version section
*/
/**
* @name makeWebhookUri
* @function
* Creates a URI object for a given pathName
* @param {object} [options] - An options object specifying uri information
*/
makeWebhookUri({ pathname, intermediatePath }) {
const intermediateToUse = this.intermediatePath || intermediatePath;
const tempPath = intermediateToUse || `/rest/webhooks/${this.webhookVersion}`;
const uri = url.format({
protocol: this.protocol,
hostname: this.host,
port: this.port,
pathname: `${this.base}${tempPath}${pathname}`,
});
return decodeURIComponent(uri);
}
/**
* @typedef makeWebhookUriOptions
* @type {object}
* @property {string} pathname - The url after the /rest/webhooks
* @property {string} intermediatePath - If specified will overwrite the /rest/webhooks section
*/
/**
* @name makeSprintQueryUri
* @function
* Creates a URI object for a given pathName
* @param {object} [options] - The url after the /rest/
*/
makeSprintQueryUri({ pathname, query, intermediatePath }) {
const intermediateToUse = this.intermediatePath || intermediatePath;
const tempPath = intermediateToUse || `/rest/greenhopper/${this.greenhopperVersion}`;
const uri = url.format({
protocol: this.protocol,
hostname: this.host,
port: this.port,
pathname: `${this.base}${tempPath}${pathname}`,
query,
});
return decodeURIComponent(uri);
}
/**
* @typedef makeSprintQueryUriOptions
* @type {object}
* @property {string} pathname - The url after the /rest/api/version
* @property {object} query - a query object
* @property {string} intermediatePath - will overwrite the /rest/greenhopper/version section
*/
/**
* @typedef makeDevStatusUri
* @function
* Creates a URI object for a given pathname
* @arg {pathname, query, intermediatePath} obj1
* @param {string} pathname obj1.pathname - The url after the /rest/api/version
* @param {object} query obj1.query - a query object
* @param {string} intermediatePath obj1.intermediatePath - If specified will overwrite the
* /rest/dev-status/latest/issue/detail section
*/
makeDevStatusUri({ pathname, query, intermediatePath }) {
const intermediateToUse = this.intermediatePath || intermediatePath;
const tempPath = intermediateToUse || '/rest/dev-status/latest/issue';
const uri = url.format({
protocol: this.protocol,
hostname: this.host,
port: this.port,
pathname: `${this.base}${tempPath}${pathname}`,
query,
});
return decodeURIComponent(uri);
}
/**
* @name makeAgile1Uri
* @function
* Creates a URI object for a given pathname
* @param {UriOptions} object
*/
makeAgileUri(object) {
const intermediateToUse = this.intermediatePath || object.intermediatePath;
const tempPath = intermediateToUse || '/rest/agile/1.0';
const uri = url.format({
protocol: this.protocol,
hostname: this.host,
port: this.port,
pathname: `${this.base}${tempPath}${object.pathname}`,
query: object.query,
});
return decodeURIComponent(uri);
}
/**
* @name doRequest
* @function
* Does a request based on the requestOptions object
* @param {object} requestOptions - fields on this object get posted as a request header for
* requests to jira
*/
async doRequest(requestOptions) {
const options = {
...this.baseOptions,
...requestOptions,
};
const response = await this.request(options);
if (response) {
if (Array.isArray(response.errorMessages) && response.errorMessages.length > 0) {
throw new Error(response.errorMessages.join(', '));
}
}
return response;
}
/**
* @name findIssue
* @function
* Find an issue in jira
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id290709)
* @param {string} issueNumber - The issue number to search for including the project key
* @param {string} expand - The resource expansion to return additional fields in the response
* @param {string} fields - Comma separated list of field ids or keys to retrieve
* @param {string} properties - Comma separated list of properties to retrieve
* @param {boolean} fieldsByKeys - False by default, used to retrieve fields by key instead of id
*/
findIssue(issueNumber, expand, fields, properties, fieldsByKeys) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueNumber}`,
query: {
expand: expand || '',
fields: fields || '*all',
properties: properties || '*all',
fieldsByKeys: fieldsByKeys || false,
},
})));
}
/**
* @name downloadAttachment
* @function
* Download an attachment
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id288524)
* @param {object} attachment - the attachment
*/
downloadAttachment(attachment) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/attachment/${attachment.id}/${attachment.filename}`,
intermediatePath: '/secure',
encode: true,
}), { json: false, encoding: null }));
}
/**
* @name deleteAttachment
* @function
* Remove the attachment
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issue-attachments/#api-rest-api-3-attachment-id-delete)
* @param {string} attachmentId - the attachment id
*/
deleteAttachment(attachmentId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/attachment/${attachmentId}`,
}), { method: 'DELETE', json: false, encoding: null }));
}
/**
* @name getUnresolvedIssueCount
* @function
* Get the unresolved issue count
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id288524)
* @param {string} version - the version of your product you want to find the unresolved
* issues of.
*/
async getUnresolvedIssueCount(version) {
const requestHeaders = this.makeRequestHeader(
this.makeUri({
pathname: `/version/${version}/unresolvedIssueCount`,
}),
);
const response = await this.doRequest(requestHeaders);
return response.issuesUnresolvedCount;
}
/**
* @name getProject
* @function
* Get the Project by project key
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id289232)
* @param {string} project - key for the project
*/
getProject(project) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/project/${project}`,
})));
}
/**
* @name createProject
* @function
* Create a new Project
* [Jira Doc](https://docs.atlassian.com/jira/REST/latest/#api/2/project-createProject)
* @param {object} project - with specs
*/
createProject(project) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/project/',
}), {
method: 'POST',
body: project,
}));
}
/** Find the Rapid View for a specified project
* @name findRapidView
* @function
* @param {string} projectName - name for the project
*/
async findRapidView(projectName) {
const response = await this.doRequest(this.makeRequestHeader(this.makeSprintQueryUri({
pathname: '/rapidviews/list',
})));
if (typeof projectName === 'undefined' || projectName === null) return response.views;
const rapidViewResult = response.views
.find((x) => x.name.toLowerCase() === projectName.toLowerCase());
return rapidViewResult;
}
/** Get the most recent sprint for a given rapidViewId
* @name getLastSprintForRapidView
* @function
* @param {string} rapidViewId - the id for the rapid view
*/
async getLastSprintForRapidView(rapidViewId) {
const response = await this.doRequest(
this.makeRequestHeader(this.makeSprintQueryUri({
pathname: `/sprintquery/${rapidViewId}`,
})),
);
return response.sprints.pop();
}
/** Get the issues for a rapidView / sprint
* @name getSprintIssues
* @function
* @param {string} rapidViewId - the id for the rapid view
* @param {string} sprintId - the id for the sprint
*/
getSprintIssues(rapidViewId, sprintId) {
return this.doRequest(this.makeRequestHeader(this.makeSprintQueryUri({
pathname: '/rapid/charts/sprintreport',
query: {
rapidViewId,
sprintId,
},
})));
}
/** Get a list of Sprints belonging to a Rapid View
* @name listSprints
* @function
* @param {string} rapidViewId - the id for the rapid view
*/
listSprints(rapidViewId) {
return this.doRequest(this.makeRequestHeader(this.makeSprintQueryUri({
pathname: `/sprintquery/${rapidViewId}`,
})));
}
/** Get details about a Sprint
* @name getSprint
* @function
* @param {string} sprintId - the id for the sprint view
*/
getSprint(sprintId) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/sprint/${sprintId}`,
})));
}
/** Add an issue to the project's current sprint
* @name addIssueToSprint
* @function
* @param {string} issueId - the id of the existing issue
* @param {string} sprintId - the id of the sprint to add it to
*/
addIssueToSprint(issueId, sprintId) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/sprint/${sprintId}/issue`,
}), {
method: 'POST',
body: {
issues: [issueId],
},
}));
}
/** Create an issue link between two issues
* @name issueLink
* @function
* @param {object} link - a link object formatted how the Jira API specifies
*/
issueLink(link) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/issueLink',
}), {
method: 'POST',
followAllRedirects: true,
body: link,
}));
}
/** List all issue link types jira knows about
* [Jira Doc](https://docs.atlassian.com/software/jira/docs/api/REST/8.5.0/#api/2/issueLinkType-getIssueLinkTypes)
* @name listIssueLinkTypes
* @function
*/
listIssueLinkTypes() {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/issueLinkType',
})));
}
/** Retrieves the remote links associated with the given issue.
* @name getRemoteLinks
* @function
* @param {string} issueNumber - the issue number to find remote links for.
*/
getRemoteLinks(issueNumber) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueNumber}/remotelink`,
})));
}
/**
* @name createRemoteLink
* @function
* Creates a remote link associated with the given issue.
* @param {string} issueNumber - The issue number to create the remotelink under
* @param {object} remoteLink - the remotelink object as specified by the Jira API
*/
createRemoteLink(issueNumber, remoteLink) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueNumber}/remotelink`,
}), {
method: 'POST',
body: remoteLink,
}));
}
/**
* @name deleteRemoteLink
* @function
* Delete a remote link with given issueNumber and id
* @param {string} issueNumber - The issue number to delete the remotelink under
* @param {string} id the remotelink id
*/
deleteRemoteLink(issueNumber, id) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueNumber}/remotelink/${id}`,
}), {
method: 'DELETE',
followAllRedirects: true,
}));
}
/** Get Versions for a project
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id289653)
* @name getVersions
* @function
* @param {string} project - A project key to get versions for
*/
getVersions(project) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/project/${project}/versions`,
})));
}
/** Get details of single Version in project
* [Jira Doc](https://docs.atlassian.com/jira/REST/cloud/#api/2/version-getVersion)
* @name getVersion
* @function
* @param {string} version - The id of this version
*/
getVersion(version) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/version/${version}`,
})));
}
/** Create a version
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id288232)
* @name createVersion
* @function
* @param {object} version - an object of the new version
*/
createVersion(version) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/version',
}), {
method: 'POST',
followAllRedirects: true,
body: version,
}));
}
/** Update a version
* [Jira Doc](https://docs.atlassian.com/jira/REST/latest/#d2e510)
* @name updateVersion
* @function
* @param {object} version - an new object of the version to update
*/
updateVersion(version) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/version/${version.id}`,
}), {
method: 'PUT',
followAllRedirects: true,
body: version,
}));
}
/** Delete a version
* [Jira Doc](https://docs.atlassian.com/jira/REST/latest/#api/2/version-delete)
* @name deleteVersion
* @function
* @param {string} versionId - the ID of the version to delete
* @param {string} moveFixIssuesToId - when provided, existing fixVersions will be moved
* to this ID. Otherwise, the deleted version will be removed from all
* issue fixVersions.
* @param {string} moveAffectedIssuesToId - when provided, existing affectedVersions will
* be moved to this ID. Otherwise, the deleted version will be removed
* from all issue affectedVersions.
*/
deleteVersion(versionId, moveFixIssuesToId, moveAffectedIssuesToId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/version/${versionId}`,
}), {
method: 'DELETE',
followAllRedirects: true,
qs: {
moveFixIssuesTo: moveFixIssuesToId,
moveAffectedIssuesTo: moveAffectedIssuesToId,
},
}));
}
/** Move version
* [Jira Doc](https://docs.atlassian.com/jira/REST/cloud/#api/2/version-moveVersion)
* @name moveVersion
* @function
* @param {string} versionId - the ID of the version to delete
* @param {string} position - an object of the new position
*/
moveVersion(versionId, position) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/version/${versionId}/move`,
}), {
method: 'POST',
followAllRedirects: true,
body: position,
}));
}
/** Pass a search query to Jira
* [Jira Doc](https://docs.atlassian.com/jira/REST/latest/#d2e4424)
* @name searchJira
* @function
* @param {string} searchString - jira query string in JQL
* @param {object} optional - object containing any of the following properties
* @param {integer} [optional.startAt=0]: optional starting index number
* @param {integer} [optional.maxResults=50]: optional The maximum number of items to
* return per page. To manage page size, Jira may return fewer items per
* page where a large number of fields are requested.
* @param {array} [optional.fields]: optional array of string names of desired fields
* @param {array} [optional.expand]: optional array of string names of desired expand nodes
*/
searchJira(searchString, optional = {}) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/search',
}), {
method: 'POST',
followAllRedirects: true,
body: {
jql: searchString,
...optional,
},
}));
}
/** Create a Jira user
* [Jira Doc](https://docs.atlassian.com/jira/REST/cloud/#api/2/user-createUser)
* @name createUser
* @function
* @param {object} user - Properly Formatted User object
*/
createUser(user) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/user',
}), {
method: 'POST',
followAllRedirects: true,
body: user,
}));
}
/** Search user on Jira
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#d2e3756)
* @name searchUsers
* @function
* @param {SearchUserOptions} options
*/
searchUsers({
username, query, startAt, maxResults, includeActive, includeInactive,
}) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/user/search',
query: {
username,
query,
startAt: startAt || 0,
maxResults: maxResults || 50,
includeActive: includeActive || true,
includeInactive: includeInactive || false,
},
}), {
followAllRedirects: true,
}));
}
/**
* @typedef SearchUserOptions
* @type {object}
* @property {string} username - (DEPRECATED) A query string used to search username, name or
* e-mail address
* @property {string} query - A query string that is matched against user attributes
* (displayName, and emailAddress) to find relevant users. The string can match the prefix of
* the attribute's value. For example, query=john matches a user with a displayName of John
* Smith and a user with an emailAddress of johnson@example.com. Required, unless accountId
* or property is specified.
* @property {integer} [startAt=0] - The index of the first user to return (0-based)
* @property {integer} [maxResults=50] - The maximum number of users to return
* @property {boolean} [includeActive=true] - If true, then active users are included
* in the results
* @property {boolean} [includeInactive=false] - If true, then inactive users
* are included in the results
*/
/** Get all users in group on Jira
* @name getUsersInGroup
* @function
* @param {string} groupname - A query string used to search users in group
* @param {integer} [startAt=0] - The index of the first user to return (0-based)
* @param {integer} [maxResults=50] - The maximum number of users to return (defaults to 50).
*/
getUsersInGroup(groupname, startAt = 0, maxResults = 50) {
return this.doRequest(
this.makeRequestHeader(this.makeUri({
pathname: '/group',
query: {
groupname,
expand: `users[${startAt}:${maxResults}]`,
},
}), {
followAllRedirects: true,
}),
);
}
/** Get issues related to a user
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id296043)
* @name getUsersIssues
* @function
* @param {string} username - username of user to search for
* @param {boolean} open - determines if only open issues should be returned
*/
getUsersIssues(username, open) {
const openJql = open ? ' AND status in (Open, \'In Progress\', Reopened)' : '';
return this.searchJira(`assignee = ${username.replace('@', '\\u0040')}${openJql}`, {});
}
/** Returns a user.
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-user-get)
* @name getUser
* @function
* @param {string} accountId - The accountId of user to search for
* @param {string} expand - The expand for additional info (groups,applicationRoles)
*/
getUser(accountId, expand) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/user',
query: {
accountId,
expand,
},
})));
}
/** Returns a list of all (active and inactive) users.
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-users-search-get)
* @name getUsers
* @function
* @param {integer} [startAt=0] - The index of the first user to return (0-based)
* @param {integer} [maxResults=50] - The maximum number of users to return (defaults to 50).
*/
getUsers(startAt = 0, maxResults = 100) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/users',
query: {
startAt,
maxResults,
},
})));
}
/** Add issue to Jira
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id290028)
* @name addNewIssue
* @function
* @param {object} issue - Properly Formatted Issue object
*/
addNewIssue(issue) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/issue',
}), {
method: 'POST',
followAllRedirects: true,
body: issue,
}));
}
/** Add a user as a watcher on an issue
* @name addWatcher
* @function
* @param {string} issueKey - the key of the existing issue
* @param {string} username - the jira username to add as a watcher to the issue
*/
addWatcher(issueKey, username) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueKey}/watchers`,
}), {
method: 'POST',
followAllRedirects: true,
body: username,
}));
}
/** Change an assignee on an issue
* [Jira Doc](https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-assign)
* @name assignee
* @function
* @param {string} issueKey - the key of the existing issue
* @param {string} assigneeName - the jira username to add as a new assignee to the issue
*/
updateAssignee(issueKey, assigneeName) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueKey}/assignee`,
}), {
method: 'PUT',
followAllRedirects: true,
body: { name: assigneeName },
}));
}
/** Change an assignee on an issue
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issue-issueIdOrKey-assignee-put)
* @name updateAssigneeWithId
* @function
* @param {string} issueKey - the key of the existing issue
* @param {string} userId - the jira username to add as a new assignee to the issue
*/
updateAssigneeWithId(issueKey, userId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueKey}/assignee`,
}), {
method: 'PUT',
followAllRedirects: true,
body: { accountId: userId },
}));
}
/** Delete issue from Jira
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id290791)
* @name deleteIssue
* @function
* @param {string} issueId - the Id of the issue to delete
*/
deleteIssue(issueId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}`,
}), {
method: 'DELETE',
followAllRedirects: true,
}));
}
/** Update issue in Jira
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id290878)
* @name updateIssue
* @function
* @param {string} issueId - the Id of the issue to update
* @param {object} issueUpdate - update Object as specified by the rest api
* @param {object} query - adds parameters to the query string
*/
updateIssue(issueId, issueUpdate, query = {}) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}`,
query,
}), {
body: issueUpdate,
method: 'PUT',
followAllRedirects: true,
}));
}
/** List Components
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id290489)
* @name listComponents
* @function
* @param {string} project - key for the project
*/
listComponents(project) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/project/${project}/components`,
})));
}
/** Add component to Jira
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id290028)
* @name addNewComponent
* @function
* @param {object} component - Properly Formatted Component
*/
addNewComponent(component) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/component',
}), {
method: 'POST',
followAllRedirects: true,
body: component,
}));
}
/** Update Jira component
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#api/2/component-updateComponent)
* @name updateComponent
* @function
* @param {string} componentId - the Id of the component to update
* @param {object} component - Properly Formatted Component
*/
updateComponent(componentId, component) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/component/${componentId}`,
}), {
method: 'PUT',
followAllRedirects: true,
body: component,
}));
}
/** Delete component from Jira
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-api-2-component-id-delete)
* @name deleteComponent
* @function
* @param {string} id - The ID of the component.
* @param {string} moveIssuesTo - The ID of the component to replace the deleted component.
* If this value is null no replacement is made.
*/
deleteComponent(id, moveIssuesTo) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/component/${id}`,
}), {
method: 'DELETE',
followAllRedirects: true,
qs: moveIssuesTo ? { moveIssuesTo } : null,
}));
}
/** Get count of issues assigned to the component.
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-component-id-relatedIssueCounts-get)
* @name relatedIssueCounts
* @function
* @param {string} id - Component Id.
*/
relatedIssueCounts(id) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/component/${id}/relatedIssueCounts`,
})));
}
/** Create custom Jira field
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#api/2/field-createCustomField)
* @name createCustomField
* @function
* @param {object} field - Properly formatted Field object
*/
createCustomField(field) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/field',
}), {
method: 'POST',
followAllRedirects: true,
body: field,
}));
}
/** List all fields custom and not that jira knows about.
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id290489)
* @name listFields
* @function
*/
listFields() {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/field',
})));
}
/** Add an option for a select list issue field.
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#api/2/field/{fieldKey}/option-createOption)
* @name createFieldOption
* @function
* @param {string} fieldKey - the key of the select list field
* @param {object} option - properly formatted Option object
*/
createFieldOption(fieldKey, option) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/field/${fieldKey}/option`,
}), {
method: 'POST',
followAllRedirects: true,
body: option,
}));
}
/** Returns all options defined for a select list issue field.
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#api/2/field/{fieldKey}/option-getAllOptions)
* @name listFieldOptions
* @function
* @param {string} fieldKey - the key of the select list field
*/
listFieldOptions(fieldKey) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/field/${fieldKey}/option`,
})));
}
/** Creates or updates an option for a select list issue field.
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#api/2/field/{fieldKey}/option-putOption)
* @name upsertFieldOption
* @function
* @param {string} fieldKey - the key of the select list field
* @param {string} optionId - the id of the modified option
* @param {object} option - properly formatted Option object
*/
upsertFieldOption(fieldKey, optionId, option) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/field/${fieldKey}/option/${optionId}`,
}), {
method: 'PUT',
followAllRedirects: true,
body: option,
}));
}
/** Returns an option for a select list issue field.
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#api/2/field/{fieldKey}/option-getOption)
* @name getFieldOption
* @function
* @param {string} fieldKey - the key of the select list field
* @param {string} optionId - the id of the option
*/
getFieldOption(fieldKey, optionId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/field/${fieldKey}/option/${optionId}`,
})));
}
/** Deletes an option from a select list issue field.
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#api/2/field/{fieldKey}/option-delete)
* @name deleteFieldOption
* @function
* @param {string} fieldKey - the key of the select list field
* @param {string} optionId - the id of the deleted option
*/
deleteFieldOption(fieldKey, optionId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/field/${fieldKey}/option/${optionId}`,
}), {
method: 'DELETE',
followAllRedirects: true,
}));
}
/**
* @name getIssueProperty
* @function
* Get Property of Issue by Issue and Property Id
* [Jira Doc](https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/properties-getProperty)
* @param {string} issueNumber - The issue number to search for including the project key
* @param {string} property - The property key to search for
*/
getIssueProperty(issueNumber, property) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueNumber}/properties/${property}`,
})));
}
/**
* @name getIssueChangelog
* @function
* List all changes for an issue, sorted by date, starting from the latest
* [Jira Doc](https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/changelog)
* @param {string} issueNumber - The issue number to search for including the project key
* @param {integer} [startAt=0] - optional starting index number
* @param {integer} [maxResults=50] - optional ending index number
*/
getIssueChangelog(issueNumber, startAt = 0, maxResults = 50) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueNumber}/changelog`,
query: {
startAt,
maxResults,
},
})));
}
/**
* @name getIssueWatchers
* @function
* List all watchers for an issue
* [Jira Doc](http://docs.atlassian.com/jira/REST/cloud/#api/2/issue-getIssueWatchers)
* @param {string} issueNumber - The issue number to search for including the project key
*/
getIssueWatchers(issueNumber) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueNumber}/watchers`,
})));
}
/** List all priorities jira knows about
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id290489)
* @name listPriorities
* @function
*/
listPriorities() {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/priority',
})));
}
/** List Transitions for a specific issue that are available to the current user
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id290489)
* @name listTransitions
* @function
* @param {string} issueId - get transitions available for the issue
*/
listTransitions(issueId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}/transitions`,
query: {
expand: 'transitions.fields',
},
})));
}
/** Transition issue in Jira
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id290489)
* @name transitionsIssue
* @function
* @param {string} issueId - the Id of the issue to delete
* @param {object} issueTransition - transition object from the jira rest API
*/
transitionIssue(issueId, issueTransition) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}/transitions`,
}), {
body: issueTransition,
method: 'POST',
followAllRedirects: true,
}));
}
/** List all Viewable Projects
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id289193)
* @name listProjects
* @function
*/
listProjects() {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/project',
})));
}
/** Add a comment to an issue
* [Jira Doc](https://docs.atlassian.com/jira/REST/latest/#id108798)
* @name addComment
* @function
* @param {string} issueId - Issue to add a comment to
* @param {string} comment - string containing comment
*/
addComment(issueId, comment) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}/comment`,
}), {
body: {
body: comment,
},
method: 'POST',
followAllRedirects: true,
}));
}
/** Add a comment to an issue, supports full comment object
* [Jira Doc](https://docs.atlassian.com/jira/REST/latest/#id108798)
* @name addCommentAdvanced
* @function
* @param {string} issueId - Issue to add a comment to
* @param {object} comment - The object containing your comment data
*/
addCommentAdvanced(issueId, comment) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}/comment`,
}), {
body: comment,
method: 'POST',
followAllRedirects: true,
}));
}
/** Update comment for an issue
* [Jira Doc](https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-updateComment)
* @name updateComment
* @function
* @param {string} issueId - Issue with the comment
* @param {string} commentId - Comment that is updated
* @param {string} comment - string containing new comment
* @param {object} [options={}] - extra options
*/
updateComment(issueId, commentId, comment, options = {}) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}/comment/${commentId}`,
}), {
body: {
body: comment,
...options,
},
method: 'PUT',
followAllRedirects: true,
}));
}
/**
* @name getComments
* @function
* Get Comments by IssueId.
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-comment-list-post)
* @param {string} issueId - this issue this comment is on
*/
getComments(issueId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}/comment`,
})));
}
/**
* @name getComment
* @function
* Get Comment by Id.
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-comment-list-post)
* @param {string} issueId - this issue this comment is on
* @param {number} commentId - the id of the comment
*/
getComment(issueId, commentId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}/comment/${commentId}`,
})));
}
/**
* @name deleteComment
* @function
* Delete Comments by Id.
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-comment-list-post)
* @param {string} issueId - this issue this comment is on
* @param {number} commentId - the id of the comment
*/
deleteComment(issueId, commentId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}/comment/${commentId}`,
}), {
method: 'DELETE',
followAllRedirects: true,
}));
}
/** Add a worklog to a project
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id291617)
* @name addWorklog
* @function
* @param {string} issueId - Issue to add a worklog to
* @param {object} worklog - worklog object from the rest API
* @param {object} newEstimate - the new value for the remaining estimate field
* @param {object} [options={}] - extra options
*/
addWorklog(issueId, worklog, newEstimate = null, options = {}) {
const query = {
adjustEstimate: newEstimate ? 'new' : 'auto',
...newEstimate ? { newEstimate } : {},
...options,
};
const header = {
uri: this.makeUri({
pathname: `/issue/${issueId}/worklog`,
query,
}),
body: worklog,
method: 'POST',
'Content-Type': 'application/json',
json: true,
};
return this.doRequest(header);
}
/** Get ids of worklogs modified since
* [Jira Doc](https://docs.atlassian.com/jira/REST/cloud/#api/2/worklog-getWorklogsForIds)
* @name updatedWorklogs
* @function
* @param {number} since - a date time in unix timestamp format since when updated worklogs
* will be returned.
* @param {string} expand - ptional comma separated list of parameters to expand: properties
* (provides worklog properties).
*/
updatedWorklogs(since, expand) {
const header = {
uri: this.makeUri({
pathname: '/worklog/updated',
query: { since, expand },
}),
method: 'GET',
'Content-Type': 'application/json',
json: true,
};
return this.doRequest(header);
}
/** Delete worklog from issue
* [Jira Doc](https://docs.atlassian.com/jira/REST/latest/#d2e1673)
* @name deleteWorklog
* @function
* @param {string} issueId - the Id of the issue to delete
* @param {string} worklogId - the Id of the worklog in issue to delete
*/
deleteWorklog(issueId, worklogId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}/worklog/${worklogId}`,
}), {
method: 'DELETE',
followAllRedirects: true,
}));
}
/** Deletes an issue link.
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-issueLink-linkId-delete)
* @name deleteIssueLink
* @function
* @param {string} linkId - the Id of the issue link to delete
*/
deleteIssueLink(linkId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issueLink/${linkId}`,
}), {
method: 'DELETE',
followAllRedirects: true,
}));
}
/** Returns worklog details for a list of worklog IDs.
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-worklog-list-post)
* @name getWorklogs
* @function
* @param {array} worklogsIDs - a list of worklog IDs.
* @param {string} expand - expand to include additional information about worklogs
*
*/
getWorklogs(worklogsIDs, expand) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/worklog/list',
query: {
expand,
},
}), {
method: 'POST',
body: {
ids: worklogsIDs,
},
}));
}
/** Get worklogs list from a given issue
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-issue-issueIdOrKey-worklog-get)
* @name getIssueWorklogs
* @function
* @param {string} issueId - the Id of the issue to find worklogs for
* @param {integer} [startAt=0] - optional starting index number
* @param {integer} [maxResults=1000] - optional ending index number
*/
getIssueWorklogs(issueId, startAt = 0, maxResults = 1000) {
return this.doRequest(this.makeRequestHeader(
this.makeUri({
pathname: `/issue/${issueId}/worklog`,
query: {
startAt,
maxResults,
},
}),
));
}
/** List all Issue Types jira knows about
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id295946)
* @name listIssueTypes
* @function
*/
listIssueTypes() {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/issuetype',
})));
}
/** Register a webhook
* [Jira Doc](https://developer.atlassian.com/display/JIRADEV/JIRA+Webhooks+Overview)
* @name registerWebhook
* @function
* @param {object} webhook - properly formatted webhook
*/
registerWebhook(webhook) {
return this.doRequest(this.makeRequestHeader(this.makeWebhookUri({
pathname: '/webhook',
}), {
method: 'POST',
body: webhook,
}));
}
/** List all registered webhooks
* [Jira Doc](https://developer.atlassian.com/display/JIRADEV/JIRA+Webhooks+Overview)
* @name listWebhooks
* @function
*/
listWebhooks() {
return this.doRequest(this.makeRequestHeader(this.makeWebhookUri({
pathname: '/webhook',
})));
}
/** Get a webhook by its ID
* [Jira Doc](https://developer.atlassian.com/display/JIRADEV/JIRA+Webhooks+Overview)
* @name getWebhook
* @function
* @param {string} webhookID - id of webhook to get
*/
getWebhook(webhookID) {
return this.doRequest(this.makeRequestHeader(this.makeWebhookUri({
pathname: `/webhook/${webhookID}`,
})));
}
/** Delete a registered webhook
* [Jira Doc](https://developer.atlassian.com/display/JIRADEV/JIRA+Webhooks+Overview)
* @name issueLink
* @function
* @param {string} webhookID - id of the webhook to delete
*/
deleteWebhook(webhookID) {
return this.doRequest(this.makeRequestHeader(this.makeWebhookUri({
pathname: `/webhook/${webhookID}`,
}), {
method: 'DELETE',
}));
}
/** Describe the currently authenticated user
* [Jira Doc](http://docs.atlassian.com/jira/REST/latest/#id2e865)
* @name getCurrentUser
* @function
*/
getCurrentUser() {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/myself',
})));
}
/** Retrieve the backlog of a certain Rapid View
* @name getBacklogForRapidView
* @function
* @param {string} rapidViewId - rapid view id
*/
getBacklogForRapidView(rapidViewId) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/xboard/plan/backlog/data',
query: {
rapidViewId,
},
})));
}
/** Add attachment to a Issue
* [Jira Doc](https://docs.atlassian.com/jira/REST/latest/#api/2/issue/{issueIdOrKey}/attachments-addAttachment)
* @name addAttachmentOnIssue
* @function
* @param {string} issueId - issue id
* @param {object} readStream - readStream object from fs
*/
addAttachmentOnIssue(issueId, readStream) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}/attachments`,
}), {
method: 'POST',
headers: {
'X-Atlassian-Token': 'nocheck',
},
formData: {
file: readStream,
},
}));
}
/** Notify people related to issue
* [Jira Doc](https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-notify)
* @name issueNotify
* @function
* @param {string} issueId - issue id
* @param {object} notificationBody - properly formatted body
*/
issueNotify(issueId, notificationBody) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/issue/${issueId}/notify`,
}), {
method: 'POST',
body: notificationBody,
}));
}
/** Get list of possible statuses
* [Jira Doc](https://docs.atlassian.com/jira/REST/latest/#api/2/status-getStatuses)
* @name listStatus
* @function
*/
listStatus() {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/status',
})));
}
/** Get a Dev-Status summary by issue ID
* @name getDevStatusSummary
* @function
* @param {string} issueId - id of issue to get
*/
getDevStatusSummary(issueId) {
return this.doRequest(this.makeRequestHeader(this.makeDevStatusUri({
pathname: '/summary',
query: {
issueId,
},
})));
}
/** Get a Dev-Status detail by issue ID
* @name getDevStatusDetail
* @function
* @param {string} issueId - id of issue to get
* @param {string} applicationType - type of application (stash, bitbucket)
* @param {string} dataType - info to return (repository, pullrequest)
*/
getDevStatusDetail(issueId, applicationType, dataType) {
return this.doRequest(this.makeRequestHeader(this.makeDevStatusUri({
pathname: '/detail',
query: {
issueId,
applicationType,
dataType,
},
})));
}
/** Get issue
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/issue-getIssue)
* @name getIssue
* @function
* @param {string} issueIdOrKey - Id of issue
* @param {string} [fields] - The list of fields to return for each issue.
* @param {string} [expand] - A comma-separated list of the parameters to expand.
*/
getIssue(issueIdOrKey, fields, expand) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/issue/${issueIdOrKey}`,
query: {
fields,
expand,
},
})));
}
/** Move issues to backlog
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/backlog-moveIssuesToBacklog)
* @name moveToBacklog
* @function
* @param {array} issues - id or key of issues to get
*/
moveToBacklog(issues) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: '/backlog/issue',
}), {
method: 'POST',
body: {
issues,
},
}));
}
/** Get all boards
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getAllBoards)
* @name getAllBoards
* @function
* @param {number} [startAt=0] - The starting index of the returned boards.
* @param {number} [maxResults=50] - The maximum number of boards to return per page.
* @param {string} [type] - Filters results to boards of the specified type.
* @param {string} [name] - Filters results to boards that match the specified name.
* @param {string} [projectKeyOrId] - Filters results to boards that are relevant to a project.
*/
getAllBoards(startAt = 0, maxResults = 50, type, name, projectKeyOrId) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: '/board',
query: {
startAt,
maxResults,
type,
name,
...projectKeyOrId && { projectKeyOrId },
},
})));
}
/** Create Board
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-createBoard)
* @name createBoard
* @function
* @param {object} boardBody - Board name, type and filter Id is required.
* @param {string} boardBody.type - Valid values: scrum, kanban
* @param {string} boardBody.name - Must be less than 255 characters.
* @param {string} boardBody.filterId - Id of a filter that the user has permissions to view.
*/
createBoard(boardBody) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: '/board',
}), {
method: 'POST',
body: boardBody,
}));
}
/** Get Board
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getBoard)
* @name getBoard
* @function
* @param {string} boardId - Id of board to retrieve
*/
getBoard(boardId) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}`,
})));
}
/** Delete Board
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-deleteBoard)
* @name deleteBoard
* @function
* @param {string} boardId - Id of board to retrieve
*/
deleteBoard(boardId) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}`,
}), {
method: 'DELETE',
}));
}
/** Get issues for backlog
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getIssuesForBacklog)
* @name getIssuesForBacklog
* @function
* @param {string} boardId - Id of board to retrieve
* @param {number} [startAt=0] - The starting index of the returned issues. Base index: 0.
* @param {number} [maxResults=50] - The maximum number of issues to return per page. Default: 50.
* @param {string} [jql] - Filters results using a JQL query.
* @param {boolean} [validateQuery] - Specifies whether to validate the JQL query or not.
* Default: true.
* @param {string} [fields] - The list of fields to return for each issue.
*/
getIssuesForBacklog(boardId, startAt = 0, maxResults = 50, jql, validateQuery = true, fields) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/backlog`,
query: {
startAt,
maxResults,
jql,
validateQuery,
fields,
},
})));
}
/** Get Configuration
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getConfiguration)
* @name getConfiguration
* @function
* @param {string} boardId - Id of board to retrieve
*/
getConfiguration(boardId) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/configuration`,
})));
}
/** Get issues for board
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getIssuesForBoard)
* @name getIssuesForBoard
* @function
* @param {string} boardId - Id of board to retrieve
* @param {number} [startAt=0] - The starting index of the returned issues. Base index: 0.
* @param {number} [maxResults=50] - The maximum number of issues to return per page. Default: 50.
* @param {string} [jql] - Filters results using a JQL query.
* @param {boolean} [validateQuery] - Specifies whether to validate the JQL query or not.
* Default: true.
* @param {string} [fields] - The list of fields to return for each issue.
*/
getIssuesForBoard(boardId, startAt = 0, maxResults = 50, jql, validateQuery = true, fields) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/issue`,
query: {
startAt,
maxResults,
jql,
validateQuery,
fields,
},
})));
}
/** Get issue estimation for board
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/issue-getIssueEstimationForBoard)
* @name getIssueEstimationForBoard
* @function
* @param {string} issueIdOrKey - Id of issue
* @param {number} boardId - The id of the board required to determine which field
* is used for estimation.
*/
getIssueEstimationForBoard(issueIdOrKey, boardId) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/issue/${issueIdOrKey}/estimation`,
query: {
boardId,
},
})));
}
/** Get Epics
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/epic-getEpics)
* @name getEpics
* @function
* @param {string} boardId - Id of board to retrieve
* @param {number} [startAt=0] - The starting index of the returned epics. Base index: 0.
* @param {number} [maxResults=50] - The maximum number of epics to return per page. Default: 50.
* @param {string} [done] - Filters results to epics that are either done or not done.
* Valid values: true, false.
*/
getEpics(boardId, startAt = 0, maxResults = 50, done) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/epic`,
query: {
startAt,
maxResults,
done,
},
})));
}
/** Get board issues for epic
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/epic-getIssuesForEpic)
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/epic-getIssuesWithoutEpic)
* @name getBoardIssuesForEpic
* @function
* @param {string} boardId - Id of board to retrieve
* @param {string} epicId - Id of epic to retrieve, specify 'none' to get issues without an epic.
* @param {number} [startAt=0] - The starting index of the returned issues. Base index: 0.
* @param {number} [maxResults=50] - The maximum number of issues to return per page. Default: 50.
* @param {string} [jql] - Filters results using a JQL query.
* @param {boolean} [validateQuery] - Specifies whether to validate the JQL query or not.
* Default: true.
* @param {string} [fields] - The list of fields to return for each issue.
*/
getBoardIssuesForEpic(
boardId,
epicId,
startAt = 0,
maxResults = 50,
jql,
validateQuery = true,
fields,
) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/epic/${epicId}/issue`,
query: {
startAt,
maxResults,
jql,
validateQuery,
fields,
},
})));
}
/** Estimate issue for board
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/issue-estimateIssueForBoard)
* @name estimateIssueForBoard
* @function
* @param {string} issueIdOrKey - Id of issue
* @param {number} boardId - The id of the board required to determine which field
* is used for estimation.
* @param {string} body - value to set
*/
estimateIssueForBoard(issueIdOrKey, boardId, body) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/issue/${issueIdOrKey}/estimation`,
query: {
boardId,
},
}), {
method: 'PUT',
body,
}));
}
/** Rank Issues
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/issue-rankIssues)
* @name rankIssues
* @function
* @param {string} body - value to set
*/
rankIssues(body) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: '/issue/rank',
}), {
method: 'PUT',
body,
}));
}
/** Get Projects
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/project-getProjects)
* @name getProjects
* @function
* @param {string} boardId - Id of board to retrieve
* @param {number} [startAt=0] - The starting index of the returned projects. Base index: 0.
* @param {number} [maxResults=50] - The maximum number of projects to return per page.
* Default: 50.
*/
getProjects(boardId, startAt = 0, maxResults = 50) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/project`,
query: {
startAt,
maxResults,
},
})));
}
/** Get Projects Full
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/project-getProjectsFull)
* @name getProjectsFull
* @function
* @param {string} boardId - Id of board to retrieve
*/
getProjectsFull(boardId) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/project/full`,
})));
}
/** Get Board Properties Keys
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/properties-getPropertiesKeys)
* @name getBoardPropertiesKeys
* @function
* @param {string} boardId - Id of board to retrieve
*/
getBoardPropertiesKeys(boardId) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/properties`,
})));
}
/** Delete Board Property
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/properties-deleteProperty)
* @name deleteBoardProperty
* @function
* @param {string} boardId - Id of board to retrieve
* @param {string} propertyKey - Id of property to delete
*/
deleteBoardProperty(boardId, propertyKey) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/properties/${propertyKey}`,
}), {
method: 'DELETE',
}));
}
/** Set Board Property
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/properties-setProperty)
* @name setBoardProperty
* @function
* @param {string} boardId - Id of board to retrieve
* @param {string} propertyKey - Id of property to delete
* @param {string} body - value to set, for objects make sure to stringify first
*/
setBoardProperty(boardId, propertyKey, body) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/properties/${propertyKey}`,
}), {
method: 'PUT',
body,
}));
}
/** Get Board Property
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/properties-getProperty)
* @name getBoardProperty
* @function
* @param {string} boardId - Id of board to retrieve
* @param {string} propertyKey - Id of property to retrieve
*/
getBoardProperty(boardId, propertyKey) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/properties/${propertyKey}`,
})));
}
/** Get All Sprints
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint-getAllSprints)
* @name getAllSprints
* @function
* @param {string} boardId - Id of board to retrieve
* @param {number} [startAt=0] - The starting index of the returned sprints. Base index: 0.
* @param {number} [maxResults=50] - The maximum number of sprints to return per page.
* Default: 50.
* @param {string} [state] - Filters results to sprints in specified states.
* Valid values: future, active, closed.
*/
getAllSprints(boardId, startAt = 0, maxResults = 50, state) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/sprint`,
query: {
startAt,
maxResults,
state,
},
})));
}
/** Get Board issues for sprint
* [Jira Doc](https://developer.atlassian.com/cloud/jira/software/rest/api-group-board/#api-agile-1-0-board-boardid-sprint-sprintid-issue-get)
* @name getBoardIssuesForSprint
* @function
* @param {string} boardId - Id of board to retrieve
* @param {string} sprintId - Id of sprint to retrieve
* @param {number} [startAt=0] - The starting index of the returned issues. Base index: 0.
* @param {number} [maxResults=50] - The maximum number of issues to return per page. Default: 50.
* @param {string} [jql] - Filters results using a JQL query.
* @param {boolean} [validateQuery] - Specifies whether to validate the JQL query or not.
* Default: true.
* @param {string} [fields] - The list of fields to return for each issue.
* @param {string} [expand] - A comma-separated list of the parameters to expand.
*/
getBoardIssuesForSprint(
boardId,
sprintId,
startAt = 0,
maxResults = 50,
jql,
validateQuery = true,
fields,
expand,
) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/sprint/${sprintId}/issue`,
query: {
startAt,
maxResults,
jql,
validateQuery,
fields,
expand,
},
})));
}
/** Get All Versions
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/version-getAllVersions)
* @name getAllVersions
* @function
* @param {string} boardId - Id of board to retrieve
* @param {number} [startAt=0] - The starting index of the returned versions. Base index: 0.
* @param {number} [maxResults=50] - The maximum number of versions to return per page.
* Default: 50.
* @param {string} [released] - Filters results to versions that are either released or
* unreleased.Valid values: true, false.
*/
getAllVersions(boardId, startAt = 0, maxResults = 50, released) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/board/${boardId}/version`,
query: {
startAt,
maxResults,
released,
},
})));
}
/** Get Filter
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/filter)
* @name getFilter
* @function
* @param {string} filterId - Id of filter to retrieve
*/
getFilter(filterId) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/filter/${filterId}`,
})));
}
/** Get Epic
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/epic-getEpic)
* @name getEpic
* @function
* @param {string} epicIdOrKey - Id of epic to retrieve
*/
getEpic(epicIdOrKey) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/epic/${epicIdOrKey}`,
})));
}
/** Partially update epic
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/epic-partiallyUpdateEpic)
* @name partiallyUpdateEpic
* @function
* @param {string} epicIdOrKey - Id of epic to retrieve
* @param {string} body - value to set, for objects make sure to stringify first
*/
partiallyUpdateEpic(epicIdOrKey, body) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/epic/${epicIdOrKey}`,
}), {
method: 'POST',
body,
}));
}
/** Get issues for epic
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/epic-getIssuesForEpic)
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/epic-getIssuesWithoutEpic)
* @name getIssuesForEpic
* @function
* @param {string} epicId - Id of epic to retrieve, specify 'none' to get issues without an epic.
* @param {number} [startAt=0] - The starting index of the returned issues. Base index: 0.
* @param {number} [maxResults=50] - The maximum number of issues to return per page. Default: 50.
* @param {string} [jql] - Filters results using a JQL query.
* @param {boolean} [validateQuery] - Specifies whether to validate the JQL query or not.
* Default: true.
* @param {string} [fields] - The list of fields to return for each issue.
*/
getIssuesForEpic(
epicId,
startAt = 0,
maxResults = 50,
jql,
validateQuery = true,
fields,
) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/epic/${epicId}/issue`,
query: {
startAt,
maxResults,
jql,
validateQuery,
fields,
},
})));
}
/** Move Issues to Epic
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/epic-moveIssuesToEpic)
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/epic-removeIssuesFromEpic)
* @name moveIssuesToEpic
* @function
* @param {string} epicIdOrKey - Id of epic to move issue to, or 'none' to remove from epic
* @param {array} issues - array of issues to move
*/
moveIssuesToEpic(epicIdOrKey, issues) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/epic/${epicIdOrKey}/issue`,
}), {
method: 'POST',
body: {
issues,
},
}));
}
/** Rank Epics
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/epic-rankEpics)
* @name rankEpics
* @function
* @param {string} epicIdOrKey - Id of epic
* @param {string} body - value to set
*/
rankEpics(epicIdOrKey, body) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/epic/${epicIdOrKey}/rank`,
}), {
method: 'PUT',
body,
}));
}
/**
* @name getServerInfo
* @function
* Get server info
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-api-2-serverInfo-get)
*/
getServerInfo() {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/serverInfo',
})));
}
/**
* @name getIssueCreateMetadata
* @param {object} optional - object containing any of the following properties
* @param {array} [optional.projectIds]: optional Array of project ids to return metadata for
* @param {array} [optional.projectKeys]: optional Array of project keys to return metadata for
* @param {array} [optional.issuetypeIds]: optional Array of issuetype ids to return metadata for
* @param {array} [optional.issuetypeNames]: optional Array of issuetype names to return metadata
* for
* @param {string} [optional.expand]: optional Include additional information about issue
* metadata. Valid value is 'projects.issuetypes.fields'
* Get metadata for creating an issue.
* [Jira Doc](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-createmeta-get)
*/
getIssueCreateMetadata(optional = {}) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: '/issue/createmeta',
query: optional,
})));
}
/** Generic Get Request
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/2/)
* @name genericGet
* @function
* @param {string} endpoint - Rest API endpoint
*/
genericGet(endpoint) {
return this.doRequest(this.makeRequestHeader(this.makeUri({
pathname: `/${endpoint}`,
})));
}
/** Generic Get Request to the Agile API
* [Jira Doc](https://docs.atlassian.com/jira-software/REST/cloud/2/)
* @name genericGet
* @function
* @param {string} endpoint - Rest API endpoint
*/
genericAgileGet(endpoint) {
return this.doRequest(this.makeRequestHeader(this.makeAgileUri({
pathname: `/${endpoint}`,
})));
}
}