Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 34 additions & 41 deletions backend/scripts/version-check-summary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,35 @@ const colors = {
red: '\x1b[31m',
cyan: '\x1b[36m',
white: '\x1b[37m',
bgGreen: '\x1b[42m',
bgYellow: '\x1b[43m',
bgRed: '\x1b[41m',
};

// Emoji regex to match common emojis (they take 2 columns in terminal)
const emojiRegex = /\p{Emoji_Presentation}|\p{Extended_Pictographic}/gu;

function getDisplayWidth(str: string): number {
// Remove ANSI codes first
// eslint-disable-next-line no-control-regex
const plain = str.replace(/\x1b\[[0-9;]*m/g, '');
// Count emojis (each takes 2 columns but counts as 1-2 chars)
const emojis = plain.match(emojiRegex) || [];
// Base length minus emoji chars, plus 2 per emoji for display width
const baseLen = [...plain].length;
return baseLen + emojis.length; // Add 1 extra column per emoji
}

function printBox(lines: string[], borderColor: string) {
const maxLen = Math.max(...lines.map((l) => getDisplayWidth(l)));
const width = maxLen + 4;
const border = '─'.repeat(width - 2);
// Extra spaces after emojis to ensure visible gap across terminal fonts.
const labels = {
ok: `${colors.green}${colors.bold}✅ UP TO DATE${colors.reset}`,
upgrade: `${colors.yellow}${colors.bold}⚠️ UPDATE AVAILABLE${colors.reset}`,
unsupported: `${colors.red}${colors.bold}❌ UNSUPPORTED VERSION${colors.reset}`,
skipped: `${colors.dim}${colors.bold}⚠️ VERSION CHECK SKIPPED${colors.reset}`,
};

console.log(`${borderColor}┌${border}┐${colors.reset}`);
function printSection(lines: string[], accentColor: string) {
const separator = `${accentColor}${'='.repeat(48)}${colors.reset}`;
console.log(separator);
for (const line of lines) {
const displayLen = getDisplayWidth(line);
const padding = ' '.repeat(maxLen - displayLen);
console.log(`${borderColor}│${colors.reset} ${line}${padding} ${borderColor}│${colors.reset}`);
if (line === '') {
console.log('');
} else {
console.log(` ${line}`);
}
}
console.log(`${borderColor}└${border}┘${colors.reset}`);
console.log(separator);
}

async function main() {
if (isVersionCheckDisabled(process.env)) {
printBox([`${colors.dim}Version check skipped (disabled via env)${colors.reset}`], colors.dim);
printSection(
[`${colors.dim}Version check skipped (disabled via env)${colors.reset}`],
colors.dim,
);
return;
}

Expand All @@ -57,11 +50,11 @@ async function main() {

if (result.outcome === 'unsupported') {
const lines = [
`${colors.red}${colors.bold}❌ UNSUPPORTED VERSION${colors.reset}`,
labels.unsupported,
'',
`${colors.white}Current version:${colors.reset} ${colors.red}${colors.bold}v${currentVersion}${colors.reset}`,
`${colors.white}Latest version:${colors.reset} ${colors.green}v${latest}${colors.reset}`,
`${colors.white}Min supported:${colors.reset} ${colors.yellow}v${minSupported}${colors.reset}`,
`${colors.cyan}Current version:${colors.reset} ${colors.red}${colors.bold}v${currentVersion}${colors.reset}`,
`${colors.cyan}Latest version:${colors.reset} ${colors.green}v${latest}${colors.reset}`,
`${colors.cyan}Min supported:${colors.reset} ${colors.yellow}v${minSupported}${colors.reset}`,
'',
`${colors.red}Your version is no longer supported.${colors.reset}`,
`${colors.red}Please upgrade to continue receiving updates.${colors.reset}`,
Expand All @@ -72,16 +65,16 @@ async function main() {
`${colors.cyan}${colors.bold}Upgrade:${colors.reset} ${result.response.upgrade_url}`,
);
}
printBox(lines, colors.red);
printSection(lines, colors.red);
return;
}

if (result.outcome === 'upgrade') {
const lines = [
`${colors.yellow}${colors.bold}⚠️ UPDATE AVAILABLE${colors.reset}`,
labels.upgrade,
'',
`${colors.white}Current version:${colors.reset} ${colors.yellow}v${currentVersion}${colors.reset}`,
`${colors.white}Latest version:${colors.reset} ${colors.green}${colors.bold}v${latest}${colors.reset}`,
`${colors.cyan}Current version:${colors.reset} ${colors.yellow}v${currentVersion}${colors.reset}`,
`${colors.cyan}Latest version:${colors.reset} ${colors.green}${colors.bold}v${latest}${colors.reset}`,
'',
`${colors.yellow}A newer version is available.${colors.reset}`,
];
Expand All @@ -91,27 +84,27 @@ async function main() {
`${colors.cyan}${colors.bold}Upgrade:${colors.reset} ${result.response.upgrade_url}`,
);
}
printBox(lines, colors.yellow);
printSection(lines, colors.yellow);
return;
}

// outcome === 'ok'
const lines = [
`${colors.green}${colors.bold}✅ UP TO DATE${colors.reset}`,
labels.ok,
'',
`${colors.white}Version:${colors.reset} ${colors.green}${colors.bold}v${currentVersion}${colors.reset}`,
`${colors.green}Version:${colors.reset} ${colors.green}${colors.bold}v${currentVersion}${colors.reset}`,
'',
`${colors.green}You are running the latest version.${colors.reset}`,
];
printBox(lines, colors.green);
printSection(lines, colors.green);
} catch (error) {
const lines = [
`${colors.dim}${colors.bold}⚠️ VERSION CHECK SKIPPED${colors.reset}`,
labels.skipped,
'',
`${colors.dim}Unable to contact version service.${colors.reset}`,
`${colors.dim}${error instanceof Error ? error.message : String(error)}${colors.reset}`,
];
printBox(lines, colors.dim);
printSection(lines, colors.dim);
}
}

Expand Down
Loading