Jira Data Center
С самостоятельно размещённой Jira jira.js работает через отдельную поверхность — createServerClient. Это не облачный клиент с другим адресом: Data Center отвечает по /rest/api/2, а не /rest/api/3, принимает wiki-разметку там, где облако требует Atlassian Document Format, и опознаёт пользователей по name и key, а не по accountId. Общий у них только транспорт.
import { createServerClient } from 'jira.js';
const jira = createServerClient({
host: 'https://jira.your-company.com',
auth: { type: 'bearer', token: 'ВАШ_PERSONAL_ACCESS_TOKEN' },
});
const issue = await jira.issues.getIssue({ issueIdOrKey: 'PROJ-1' });Поверхность включает платформенный API, Agile API и эндпоинты сессии одним клиентом: Data Center публикует их единым документом, поэтому отдельной фабрики для Agile здесь, в отличие от облака, нет.
Поддерживаемые версии
Сгенерировано из спецификации Jira Data Center 11.3 LTS и работает начиная с Jira Data Center 10.0. Между этими выпусками разница в девять операций из четырёхсот сорока четырёх; у каждой в документации сказано, с какого выпуска она доступна, а на более старом инстансе такой вызов отвечает 404.
Jira 9.x не поддерживается: Atlassian никогда не публиковала для неё OpenAPI-документ, а вся ветка завершила жизненный цикл 26 июня 2026 года.
Аутентификация
В Jira 11 basic-аутентификация выключена по умолчанию
Jira 11.0 отключила basic-аутентификацию как шаг к её удалению и заодно отклоняет /rest/auth/1/session. На инстансе Jira 11 с настройками по умолчанию войти можно только персональным токеном. Вернуть basic может администратор в разделе Administration → System → Authentication methods.
Персональный токен (PAT)
Механизм, который рекомендует Atlassian; доступен с Jira 8.14 и одинаково работает и на 10.x, и на 11.x. Токен создаётся в Profile → Personal Access Tokens.
const jira = createServerClient({
host: 'https://jira.your-company.com',
auth: { type: 'bearer', token: 'ВАШ_PERSONAL_ACCESS_TOKEN' },
});Логин и пароль
Обратите внимание: username, а не email. У локальной учётной записи нет адреса Atlassian, а передача email выбирает облачный вариант той же стратегии.
const jira = createServerClient({
host: 'https://jira.your-company.com',
auth: { type: 'basic', username: 'jdoe', password: 'hunter2' },
});OAuth 2.0
Data Center сам является сервером авторизации: весь поток проходит на вашем инстансе, без cloudId и без шлюза Atlassian. Администратор регистрирует приложение как incoming application link и выдаёт client id и secret.
import { createServerClient, generateServerAuthorizationUrl, exchangeServerAuthorizationCode } from 'jira.js';
const host = 'https://jira.your-company.com';
// 1. Отправляем пользователя сюда.
const url = generateServerAuthorizationUrl({
host,
clientId: 'ВАШ_CLIENT_ID',
scopes: ['READ', 'WRITE'],
redirectUri: 'https://your-app.example.com/callback',
state: 'одноразовое-значение-которое-вы-проверите',
});
// 2. Меняем код из callback на токены.
const tokens = await exchangeServerAuthorizationCode({
host,
clientId: 'ВАШ_CLIENT_ID',
clientSecret: 'ВАШ_CLIENT_SECRET',
code: 'КОД_ИЗ_CALLBACK',
redirectUri: 'https://your-app.example.com/callback',
});
// 3. Дальше клиент обновляет токен сам.
const jira = createServerClient({
host,
auth: {
type: 'oauth2Server',
accessToken: tokens.accessToken,
refreshToken: tokens.refreshToken,
clientId: 'ВАШ_CLIENT_ID',
clientSecret: 'ВАШ_CLIENT_SECRET',
redirectUri: 'https://your-app.example.com/callback',
expiresAt: Date.now() + tokens.expiresIn * 1000,
onTokenRefresh: ({ refreshToken }) => save(refreshToken),
},
});Области доступа — READ, WRITE, ADMIN и SYSTEM_ADMIN, каждая включает предыдущие.
redirectUri относится к набору для обновления, а не только к первичному обмену: провайдер Data Center проверяет его и на refresh-гранте, и без него приходит invalid_grant, который ничего не объясняет.
Вебхуки
Единственная часть этой поверхности, которую Atlassian не описывает спецификацией. createWebhook и восемь операций рядом написаны по Jersey WADL, который отдаёт живой инстанс по адресу /rest/jira-webhook/1.0/application.wadl — он описывает запросы и, при пустом элементе grammars, ничего не говорит о телах, — и по вызовам каждой из них на живом инстансе Data Center.
const webhook = await jira.webhooks.createWebhook({
name: 'issue created',
url: 'https://example.com/hooks/jira',
events: ['jira:issue_created'],
});
const statistics = await jira.webhooks.getWebhookStatistics({ webhookId: webhook.id });Живут они по /rest/jira-webhook/1.0/ — туда их перенесла Jira 10. Старый /rest/webhooks/1.0/webhook обслуживал Jira 9 и раньше и отвечает 404 на любом выпуске, который поддерживает этот клиент.
getWebhookTransitions и getLatestWebhookInvocation возвращают unknown: инстанс, который ни разу не доставил вебхук, отвечает пустым списком и 204 — описывать было нечего, а догадка была бы хуже, чем оставить уточнение типа вызывающему.
Переход с облака
| Cloud | Data Center | |
|---|---|---|
| Фабрика | createCloudClient | createServerClient |
| Импорт | jira.js/cloud | jira.js/server |
| Версия API | /rest/api/3 | /rest/api/2 |
| Agile | отдельный createAgileClient | в том же клиенте |
| Форматированный текст | Atlassian Document Format | wiki-разметка обычной строкой |
| Идентификация пользователя | accountId | name и key |
| Basic-аутентификация | email + API-токен | логин + пароль |
Поскольку поверхности описывают разные формы данных, их модели невзаимозаменяемы. Импортируйте типы из jira.js/server, а не из jira.js/cloud, и учитывайте, что несколько имён — Issue, Project, User — существуют в обеих с разным набором полей.
Локальный инстанс
В репозитории есть одноразовый Data Center для собственных живых тестов — самый быстрый способ проверить что-то на настоящем инстансе:
pnpm jira-dc:up # поднять и пройти мастер установки
pnpm test:live:server # прогнать сюиты Data Center против него
pnpm jira-dc:down # остановить и удалить данныеЗапускается Jira 10.3 LTS, холодный старт занимает десятки минут. Лицензии в репозитории нет: возьмите трёхчасовой timebomb-ключ на странице timebomb-лицензий Atlassian и сохраните его как docker/jira-dc/timebomb-license.txt до первого запуска. Чтобы проверить на самом свежем выпуске, задайте JIRA_DC_VERSION=11.3 — но там выключена basic-аутентификация, войти сюитам нечем, и против неё они не гоняются.
По умолчанию берётся 10.3, а не самый свежий выпуск, и причина в аутентификации, а не в возрасте: Jira 11.0 выключает basic-аутентификацию и вдобавок отвергает /rest/auth/1/session, так что войти можно только персональным токеном — а токен не выпустить, не залогинившись через браузер, чего headless-прогон сделать не может. На 10.3 сюиты поднимают себя сами.
Две переменные окружения в docker/jira-dc/compose.yaml несущие, если вы будете его править. ATL_DB_DRIVER обязана быть задана, иначе в сгенерированном dbconfig.xml окажется пустой <driver-class>, Jira не сможет открыть соединение, и мастер всё-таки спросит базу — со всеми полями пустыми, что читается как «переменные проигнорированы», а не «неполны». ATL_DB_TYPE обязана быть postgres72 — так Atlassian называет любой PostgreSQL, независимо от версии сервера. Переменными управляется только шаг с базой: лицензия, администратор и почта переменных не имеют и настраиваются по HTTP из scripts/lib/dcRig.ts.