initial commit

This commit is contained in:
2026-10-13 02:24:39 +03:00
commit 191b80b6b1
80 changed files with 6863 additions and 0 deletions

40
server/incidents-cli.mjs Normal file
View File

@@ -0,0 +1,40 @@
import { loadConfig } from './config.mjs';
import { openStore } from './store.mjs';
const config = loadConfig();
const args = process.argv.slice(2);
function optionsFrom(items) {
const result = {};
for (const item of items) {
const at = item.indexOf('=');
if (at <= 0 || Object.hasOwn(result, item.slice(0, at))) throw new Error('Use unique key=value options');
result[item.slice(0, at)] = item.slice(at + 1);
}
return result;
}
const store = openStore(config.dbPath);
try {
if (args[0] === 'list') {
console.log(JSON.stringify(store.incidents().map(({ signature: _signature, ...incident }) => incident), null, 2));
} else if (args[0] === 'resolve' && /^\d+$/.test(args[1] || '')) {
const options = optionsFrom(args.slice(2));
const input = Object.keys(options).length ? { messageRu: options['message-ru'], messageEn: options['message-en'] } : null;
if (!store.resolveIncident(args[1], Date.now(), input)) throw new Error('Open manual incident not found; monitor incidents close after recovery');
console.log(`Resolved incident ${args[1]}`);
} else if (args[0] === 'update' && /^\d+$/.test(args[1] || '')) {
const options = optionsFrom(args.slice(2));
store.updateIncident(args[1], { stage: options.stage, messageRu: options['message-ru'], messageEn: options['message-en'] });
console.log(`Updated incident ${args[1]}`);
} else if (args[0] === 'create') {
const options = optionsFrom(args.slice(1));
const required = ['title-ru', 'title-en', 'message-ru', 'message-en'];
if (required.some(key => !options[key]?.trim() || options[key].length > 2000)) throw new Error('Provide title-ru, title-en, message-ru, message-en, 1–2000 characters');
if (options.service && !config.services.some(service => service.id === options.service)) throw new Error('Unknown service');
const id = store.createIncident({ serviceId: options.service || null, titleRu: options['title-ru'], titleEn: options['title-en'], messageRu: options['message-ru'], messageEn: options['message-en'] });
console.log(`Created incident ${id}`);
} else {
console.log('Usage: npm run incident -- list | resolve ID ["message-ru=..." "message-en=..."] | update ID stage=investigating|identified|monitoring|postmortem "message-ru=..." "message-en=..." | create service=api "title-ru=..." "title-en=..." "message-ru=..." "message-en=..."');
process.exitCode = 1;
}
} catch (error) { console.error(error.message); process.exitCode = 1; }
finally { store.close(); }