bookr-cli
Version:
A terminal-based CLI tool to book time in Jira using the Tempo plugin by parsing your current Git branch name
193 lines • 6.22 kB
JavaScript
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { readCache, writeCache, clearCache } from './cache.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
/**
* Get package information from package.json
*/
function getPackageInfo() {
try {
const packagePath = join(__dirname, '..', '..', 'package.json');
const packageContent = readFileSync(packagePath, 'utf-8');
return JSON.parse(packageContent);
}
catch {
return { name: 'bookr-cli', version: '0.0.0' };
}
}
/**
* Compare two semantic versions
*/
function compareVersions(current, latest) {
const currentParts = current.split('.').map((part) => Number(part) || 0);
const latestParts = latest.split('.').map((part) => Number(part) || 0);
// Compare major version
if ((latestParts[0] ?? 0) > (currentParts[0] ?? 0))
return true;
if ((latestParts[0] ?? 0) < (currentParts[0] ?? 0))
return false;
// Compare minor version
if ((latestParts[1] ?? 0) > (currentParts[1] ?? 0))
return true;
if ((latestParts[1] ?? 0) < (currentParts[1] ?? 0))
return false;
// Compare patch version
return (latestParts[2] ?? 0) > (currentParts[2] ?? 0);
}
/**
* Check if we should perform an update check
* Check every 6 hours instead of 24 hours to reduce stale cache issues
*/
function shouldCheckForUpdates() {
const cache = readCache();
if (!cache)
return true;
const sixHours = 6 * 60 * 60 * 1000; // 6 hours in milliseconds
const timeSinceLastCheck = Date.now() - cache.lastCheck;
return timeSinceLastCheck > sixHours;
}
/**
* Check if cache is invalid due to version mismatch
* This handles cases where the package was updated but cache still has old data
*/
function isCacheInvalid() {
const cache = readCache();
if (!cache)
return false;
const packageInfo = getPackageInfo();
const currentVersion = packageInfo.version;
// Cache is invalid if:
// 1. Current version is newer than cached latest version (package was updated)
// 2. Current version is different from what we last checked against
return compareVersions(cache.latestVersion, currentVersion) ||
cache.currentVersion !== currentVersion;
}
/**
* Fetch latest version from npm registry
*/
async function fetchLatestVersion(packageName) {
try {
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = (await response.json());
return data.version;
}
catch (error) {
throw new Error(`Failed to fetch latest version: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Check for available updates
*/
export async function checkForUpdates() {
const packageInfo = getPackageInfo();
const currentVersion = packageInfo.version;
// Check if cache is invalid due to version changes
if (isCacheInvalid()) {
clearCache();
}
// Check cache first (but only if it's not too old and not invalid)
if (!shouldCheckForUpdates()) {
const cache = readCache();
if (cache) {
return {
current: currentVersion,
latest: cache.latestVersion,
hasUpdate: cache.updateAvailable,
isOutdated: cache.updateAvailable,
};
}
}
try {
const latestVersion = await fetchLatestVersion(packageInfo.name);
const hasUpdate = compareVersions(currentVersion, latestVersion);
// Cache the result
writeCache({
lastCheck: Date.now(),
latestVersion,
currentVersion,
updateAvailable: hasUpdate,
});
return {
current: currentVersion,
latest: latestVersion,
hasUpdate,
isOutdated: hasUpdate,
};
}
catch {
// If fetch fails, try to use cache as fallback
const cache = readCache();
if (cache) {
return {
current: currentVersion,
latest: cache.latestVersion,
hasUpdate: cache.updateAvailable,
isOutdated: cache.updateAvailable,
};
}
// If no cache available, return current version info
return {
current: currentVersion,
latest: currentVersion,
hasUpdate: false,
isOutdated: false,
};
}
}
/**
* Get update notification message
*/
export function getUpdateMessage(updateInfo) {
if (!updateInfo.hasUpdate)
return '';
const { current, latest } = updateInfo;
return `📦 Update available: ${current} → ${latest}\nRun: npm update -g bookr-cli`;
}
/**
* Display update notification if available
*/
export async function showUpdateNotification() {
try {
const updateInfo = await checkForUpdates();
const message = getUpdateMessage(updateInfo);
if (message) {
console.log(`\n${message}\n`);
}
}
catch {
// Silently fail update notifications
}
}
/**
* Force check for updates (ignores cache)
*/
export async function forceCheckForUpdates() {
const packageInfo = getPackageInfo();
const currentVersion = packageInfo.version;
try {
const latestVersion = await fetchLatestVersion(packageInfo.name);
const hasUpdate = compareVersions(currentVersion, latestVersion);
// Update cache
writeCache({
lastCheck: Date.now(),
latestVersion,
currentVersion,
updateAvailable: hasUpdate,
});
return {
current: currentVersion,
latest: latestVersion,
hasUpdate,
isOutdated: hasUpdate,
};
}
catch (error) {
throw new Error(`Failed to check for updates: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
//# sourceMappingURL=update.js.map