pinkmine/tools/sync-root-issues.mjs

135 lines
3.5 KiB
JavaScript

import { parse } from 'jsonc-parser';
import { readFileSync } from 'fs';
import { parseArgs } from 'util';
import { createInterface } from 'readline/promises';
const helpMsg = `
Синхронизация суммирующих задач
* --config=sync-root-issues.jsonc - конфигурационный файл для постановки задачи на выполнение синхронизации
* --yes - автоматически отвечать 'y'
Пример конфигурационного файла:
{
"redmineUrl": "http://redmine.my-company.local",
"redmineToken": "... ... ...",
"eventEmitterUrl": "http://localhost:3000",
"rootIds": [
123001,
130012
]
}
`;
var args = parseArgs({
options: {
config: {
type: 'string',
},
yes: {
type: 'boolean',
},
},
});
if (!args?.values?.config) {
console.log(helpMsg);
process.exit(0);
}
function readConfig(fileName) {
const rawData = readFileSync(fileName, { encoding: 'utf8' });
return parse(rawData);
}
var config = readConfig(args.values.config);
function getAllRootIssueIds(issues, res) {
for (let i = 0; i < issues.length; i++) {
const issue = issues[i];
if (issue.children && issue.children.length > 0) {
res.push(issue.id);
getAllRootIssueIds(issue.children, res);
}
}
return res;
}
async function loadIssueFromRedmine(issueId) {
const token = config?.redmineToken || '';
const redmineUrl = config?.redmineUrl || '';
const url = `${redmineUrl}/issues/${issueId}.json?include=children`;
const resp = await fetch(url, {
headers: {
'X-Redmine-API-Key': token,
},
});
const data = await resp.json();
return data?.issue || null;
}
async function loadAllRootIssueIds() {
const rootIssueIds = config?.rootIds || [];
const rootIssues = [];
for (let i = 0; i < rootIssueIds.length; i++) {
const rootIssueId = rootIssueIds[i];
const issue = await loadIssueFromRedmine(rootIssueId);
if (issue) {
rootIssues.push(issue);
}
}
const allRootIssueIds = getAllRootIssueIds(rootIssues, []);
return allRootIssueIds;
}
async function questionYesOrNo(question, yesMsg, noMsg) {
const readline = createInterface({
input: process.stdin,
output: process.stdout,
});
const answer = await readline.question(`\n${question} (y/n)\n> `);
const res = answer == 'y';
readline.close();
console.log(res ? `\n${yesMsg}` : `\n${noMsg}`);
return res;
}
async function main() {
console.log(
`Конфигурационный файл:\n${JSON.stringify(config, null, ' ')}\n`,
);
if (!args.values.yes) {
const res = await questionYesOrNo(
'Продолжаем?',
'Продолжаем...',
'Прервано',
);
if (!res) process.exit();
}
const rootIds = await loadAllRootIssueIds();
console.log(`Задачи для синхронизации - ${JSON.stringify(rootIds)}`);
if (!args.values.yes) {
const res = await questionYesOrNo(
'Продолжаем?',
'Продолжаем...',
'Прервано',
);
if (!res) process.exit();
}
console.log(`Отправка задач на синхронизацию...`);
await await fetch(
`${config.eventEmitterUrl}/redmine-event-emitter/append-issues`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(rootIds),
},
);
console.log(`Синхронизация запущена`);
}
await main();